-
Notifications
You must be signed in to change notification settings - Fork 3
MatplotlibThemes
These themes give a chart the matplotlib look in pure .NET, with no other changes needed. No Python runtime is required.
The two themes mimic matplotlib's visual style: the pre-2.0 classic look and the modern v2.0+ default. MatPlotLibNet renders both entirely on its own.
This theme uses a white background, the bgrcmyk 7-color cycle, DejaVu Sans at 12pt, and a grid that is hidden by default. The grid is hidden because matplotlib ships with plt.grid(False); users turn it on themselves.
using MatPlotLibNet;
using MatPlotLibNet.Styling;
double[] x = [0, 1, 2, 3, 4, 5];
double[] y1 = [0, 1, 4, 9, 16, 25];
double[] y2 = [0, 2, 4, 6, 8, 10];
Plt.Create()
.WithTheme(Theme.MatplotlibClassic)
.WithTitle("Classic matplotlib look")
.Plot(x, y1, s => s.Label = "Quadratic")
.Plot(x, y2, s => s.Label = "Linear")
.WithLegend()
.Save("classic.svg");| # | Hex | Name |
|---|---|---|
| 0 | #0000FF |
blue |
| 1 | #008000 |
green |
| 2 | #FF0000 |
red |
| 3 | #00BFBF |
cyan |
| 4 | #BF00BF |
magenta |
| 5 | #BFBF00 |
yellow |
| 6 | #000000 |
black |
| Property | Value |
|---|---|
| Background |
#FFFFFF (white) |
| Axes background |
#FFFFFF (white) |
| Foreground text |
#000000 (pure black) |
| Font family | DejaVu Sans, Bitstream Vera Sans, sans-serif |
| Font size | 12.0pt |
| Grid | hidden by default (Visible = false) |
| Cycle length | 7 colors |
This theme uses a white background, soft-black #262626 text, the modern tab10 10-color cycle, DejaVu Sans at 10pt, and a grid that is hidden by default. Matplotlib v2 softened pure black to this soft black on purpose.
Plt.Create()
.WithTheme(Theme.MatplotlibV2)
.WithTitle("Modern matplotlib look")
.Plot(x, y1, s => s.Label = "Quadratic")
.Plot(x, y2, s => s.Label = "Linear")
.WithLegend()
.Save("v2.svg");| # | Hex | Name |
|---|---|---|
| 0 | #1f77b4 |
blue |
| 1 | #ff7f0e |
orange |
| 2 | #2ca02c |
green |
| 3 | #d62728 |
red |
| 4 | #9467bd |
purple |
| 5 | #8c564b |
brown |
| 6 | #e377c2 |
pink |
| 7 | #7f7f7f |
gray |
| 8 | #bcbd22 |
olive |
| 9 | #17becf |
cyan |
| Property | Value |
|---|---|
| Background |
#FFFFFF (white) |
| Axes background |
#FFFFFF (white) |
| Foreground text |
#262626 (soft black) |
| Font family | DejaVu Sans, sans-serif |
| Font size | 10.0pt |
| Grid | hidden by default (Visible = false) |
| Cycle length | 10 colors |
Both themes ship with the grid off, matching matplotlib's plt.grid(False) default.
Plt.Create()
.WithTheme(Theme.MatplotlibV2)
.AddSubPlot(1, 1, 1, ax => ax
.Plot(x, y)
.ShowGrid(true)) // simple toggle
.Save("v2_with_grid.svg");Or override the theme grid via ThemeBuilder:
var v2WithGrid = Theme.CreateFrom(Theme.MatplotlibV2)
.WithGrid(g => g with { Visible = true, Color = Color.FromHex("#B0B0B0") })
.Build();| Aspect | MatplotlibClassic |
MatplotlibV2 |
Theme.Default |
|---|---|---|---|
| Era mimicked | matplotlib < 2.0 | matplotlib 2.0+ | none specifically |
| Cycle |
bgrcmyk (7) |
tab10 (10) |
tab10 (10) |
| Foreground text | pure black | soft black #262626
|
pure black |
| Font size | 12pt | 10pt | 13pt (default) |
| Grid default | off | off | on |
| Use case | retro / classic | modern Jupyter look | MatPlotLibNet's own default |
Theme.Default already uses tab10. Choose MatplotlibV2 when you want the full matplotlib look: it has a different font stack, soft-black text, and a grid that is hidden by default.
There are six community themes. Each has its own palette, font, size, and grid defaults. Applying one visibly changes the chart; no other API calls are needed.
| Theme | Palette | Font | Size | Grid |
|---|---|---|---|---|
Theme.Grayscale |
grayscale cycle (no hues) | default | default | default |
Theme.Paper |
default | serif | 11pt | off |
Theme.Presentation |
default | bold | 16pt | default |
Theme.Poster |
default | bold | 20pt | on, 1.5 linewidth |
Theme.GitHub |
GitHub brand palette | default | default | #E1E4E8 |
Theme.Minimal |
default | default | 11pt | off |
Use them the same way: Plt.Create().WithTheme(Theme.Paper)…. Contract tests check that each theme produces byte-distinct output, so a theme that collapses back to Default fails CI.
Every chart with a matplotlib equivalent is verified against a pinned matplotlib (3.10.8) reference PNG under both themes. The fidelity suite runs 146 tests (73 fixtures × 2 themes):
# regenerate reference PNGs (developers only — not run in CI)
pip install -r tools/mpl_reference/requirements.txt
python tools/mpl_reference/generate.py --all --style both
# run the dual-theme fidelity tests
dotnet run --project Tst/MatPlotLibNet.Fidelity/MatPlotLibNet.Fidelity.Tests.csprojEach test renders one MatPlotLibNet figure, exports to PNG via the SkiaSharp backend, and compares against the matplotlib reference using three metrics: RMS pixel error, block SSIM, and MaxColorDeltaE (CIE ΔE*76 across the 5 dominant colours). Failures emit a 3-panel side-by-side diff PNG (reference | actual | abs-difference heatmap) under bin/Debug/net10.0/fidelity-failures/{theme}_{name}.diff.png.
Coverage: the 73 fixtures are 12 core fixtures (line, scatter, bar, hist, pie, box, violin, heatmap, contour, polar, candlestick, errorbar), 45 Phase 5 fixtures (XY, grid, field, polar, categorical, distribution, 3D, financial, special), 15 Phase 6 fixtures (pandas_ta technical indicators), and 1 composition fixture (a multi-subplot suptitle, mathtext labels, and a mathtext legend).
The v2 fixtures use plt.style.context('default'), which is matplotlib's modern default (tab10 cycle, DejaVu Sans 10pt, soft-black #262626 foreground). This is the look that Theme.MatplotlibV2 reproduces.
An internal MatplotlibThemeFactory builds both themes through a shared Build(...) helper, so the two themes differ only where they have to: color cycle, font size, and foreground text. The font stack is a record struct (MatplotlibFontStack). It has named fields with value equality; it is not a positional tuple.
- Styling — themes, colormaps, PropCycler, custom themes
-
Accessibility —
Theme.ColorBlindSafe,Theme.HighContrast - Source
MatPlotLibNet 1.18.0