Skip to content

Fluent Cheatsheet

H.P. Gansevoort edited this page Sep 13, 2026 · 16 revisions

Coming from Python? From matplotlib to C# puts every pyplot call beside the line that draws the same chart here.

Fluent API Cheat Sheet

This page is a one-page reference for MatPlotLibNet's fluent builder API. Every chart starts at Plt.Create() and ends at an output call (ToSvg, Save, …). In between, you chain figure-level methods on FigureBuilder and per-subplot methods on AxesBuilder via AddSubPlot(..., ax => ax.Plot(...)).


1. Entry points — Plt

Call Returns Purpose
Plt.Create() FigureBuilder The normal entry point. Starts fluent construction.
Plt.Figure(width, height) Figure Creates the model directly, without the builder. Rarely used.
Plt.Mosaic("AB;CC", ...) MosaicFigureBuilder Defines the subplot layout from an ASCII-art string.
Plt.Style.Use(...) void Applies a global stylesheet (e.g. "seaborn").
Plt.Style.Context(...) StyleContext Applies a style override for the scope of a using block.

2. FigureBuilder — figure-level chaining

Sizing, title, theme

Plt.Create()
   .WithSize(900, 600)                       // px — intrinsic / viewBox size
   .WithDpi(150)                              // raster export resolution
   .WithTitle("Q1 Report")
   .WithTheme(Theme.MatplotlibV2)             // or MatplotlibClassic, HighContrast, ColorBlindSafe
   .WithBackground(Colors.White)
   .WithAltText("Accessible description")
   .WithResponsiveSvg(false)                  // opt out of v1.7.2 Phase L default (max-width:100%;height:auto)

Subplots

.AddSubPlot(1, 1, 1, ax => ax.Plot(x, y))              // classic: rows, cols, 1-based index
.AddSubPlot(new GridPosition(0, 1, 0, 2), ax => ...)   // GridSpec-based
.WithGridSpec(3, 2, heightRatios: [2, 1, 1])           // uneven row heights

Layout

.TightLayout()          // auto-compute margins from measured text
.ConstrainedLayout()    // same idea, more aggressive
.WithSubPlotSpacing(s => s with { MarginTop = 60 })    // manual override

Interactivity (SVG only — embeds JS in the output)

.WithZoomPan()               // drag-to-pan, wheel-to-zoom
.WithLegendToggle()          // click a legend entry → hide/show series
.WithRichTooltips()          // hover a point → tooltip
.WithHighlight()             // hover a series → dim others
.WithSelection()             // click to select points
.With3DRotation()            // drag a 3D plot to rotate
.WithTreemapDrilldown()      // every depth visible by default; click a parent rect to collapse its entire subtree, click again to restore (v1.7.2 Phase W "steady pictures")
.WithSankeyHover()           // hover a Sankey node → isolate reachable flow chain

Output

.ToSvg()                // string
.Save("chart.svg")      // .svg / .png / .pdf / .gif picked from extension
.SaveSvgAndPng("chart") // both at once
.ToJson(indented: true) // serialize the figure
.Build()                // Figure model (skip rendering)

Interactive browser popup (MatPlotLibNet.Interactive, async-only)

var handle = await figure.ShowAsync();   // opens a self-hosted browser popup
await handle.UpdateAsync(newFigure);     // push a new figure version

There is no synchronous Show(); it was removed in v1.13.0. Calling anything on the handle after disposal throws ObjectDisposedException.

Figure-level series shortcuts (bypass AddSubPlot)

These shortcuts are useful for single-plot figures:

Plt.Create().Plot(x, y).Save("line.svg");
Plt.Create().Bar(cats, vals).Save("bar.png");
Plt.Create().Scatter(x, y).Save("scatter.pdf");

The families supported at figure level are Plot / Scatter / Bar / Hist / Pie / Image / Heatmap / Treemap / Sunburst / Sankey / Surface / Scatter3D / Bar3D / PolarPlot / Candlestick / OhlcBar / BoxPlot / Violin and many more.


3. AxesBuilder — per-subplot chaining

Titles, labels, limits

ax.WithTitle("Revenue")
  .SetXLabel("Quarter")
  .SetYLabel("USD")
  .SetZLabel("Units")        // 3D only
  .SetXLim(0, 10)
  .SetYLim(0, 100)
  .SetXScale(AxisScale.Log)  // log, linear, symlog

Ticks & formatting

ax.SetXTickLocator(new MaxNLocator(5))
  .SetYTickLocator(new AutoLocator())
  .SetXTickFormatter(new PercentTickFormatter())
  .WithMinorTicks()
  .WithYTicksMirrored()        // ticks on both left AND right (v1.4.1)
  .WithXTicksMirrored()        // ticks on both top AND bottom (v1.4.1)
  .WithTightMargins()          // SetXMargin(0).SetYMargin(0) — data touches spines (v1.4.1, v1.7.2 Phase L.11 also skips nice-bounds expansion)
  .WithXTickLabelRotation(30)  // rotate X-tick labels (v1.7.2 Phase L.8); auto-30° when labels would overlap
  .WithYTickLabelRotation(45)  // rotate Y-tick labels (v1.7.2 Phase L.8)
  .SetXDateAxis()              // interprets X as DateTime
  .SetXDateFormat("yyyy-MM")

Spines & hiding

ax.HideTopSpine()
  .HideRightSpine()
  .HideAllAxes()               // Sankey / Treemap canvas (no spines, no ticks, no labels)
  .WithSpines(s => s with { Left = s.Left with { LineWidth = 2 } })

Legend & grid

ax.WithLegend(LegendPosition.UpperRight)
  .WithLegend(l => l with { Position = LegendPosition.OutsideRight, NCols = 2, Title = "Series" })
  .WithLegendValues()          // appends each XY series' last Y value to its legend entry
  .ShowGrid()
  .WithGrid(g => g with { Color = Colors.LightGray, LineStyle = LineStyle.Dashed })

Legend positions: there are 11 inside positions (UpperRight, UpperLeft, LowerRight, LowerLeft, Right, CenterLeft, CenterRight, LowerCenter, UpperCenter, Center, Best) and 4 outside positions (OutsideRight, OutsideLeft, OutsideTop, OutsideBottom). Constrained layout reserves space for the outside positions.

Order-independent WithLegend (v1.13.0 fix): WithLegend(position, visible) updates only Visible and Position. Every other property is preserved, whatever the call order. .WithLegendValues().WithLegend(LegendPosition.UpperRight) and the reverse order give the same result.

LegendValues last-value suffix: WithLegendValues(enabled: true) appends each labelled XYSeries' last data value to its legend entry. For example, Signal becomes Signal = 2.70; the value is formatted with invariant culture F2. Non-XY series show the label text only. The default is false.

Insets

ax.AddInset(new InsetBounds(0.55, 0.55, 0.4, 0.4), inset => inset
    .Plot(zoomX, zoomY)
    .SetXLim(2, 4));

// convenience overload — forwards to the InsetBounds overload above (canonical form, v1.13.0)
ax.AddInset(x: 0.55, y: 0.55, width: 0.4, height: 0.4, inset => inset.Plot(zoomX, zoomY));

InsetBounds(X, Y, Width, Height) is a readonly record struct. Its values are fractions (0-1) of the parent axes.

Sharing & secondary axes

ax.ShareX("time-axis")
  .WithSecondaryYAxis(y2 => y2.Bar(cats, volume).SetYLabel("Volume"))

Color & colormap (for heatmap/contour/surface)

ax.WithColorMap("viridis")     // or ColorMaps.Viridis
  .WithColorBar(cb => cb.Label = "Density")
  .WithNormalizer(new LogNormalizer(vmin: 1, vmax: 1000))

Broken / discontinuous axes

ax.WithYBreak(20, 80, BreakStyle.Zigzag)

4. Series methods — by family

Every series method takes a final optional Action<T> configure to tweak properties.

Family Methods
XY line/scatter Plot(x, y), Scatter(x, y), DensityScatter(x, y) (markers coloured by how crowded they are), ErrorBar(x, y, yErrLow, yErrHi), Step(x, y), FillBetween(x, y, y2), StackPlot(x, ySets)
Signal / realtime SignalXY(x, y) (monotonic X, fast), Signal(y, sampleRate, xStart) (sample rate and offset)
Categorical Bar(cats, vals), GroupedBar(cats, groups) (several bars per category in one call), BrokenBarH(ranges), Gantt(tasks, starts, ends), Waterfall(cats, vals), Eventplot(positions), Countplot(values)
Distribution Hist(data, bins), BoxPlot(datasets), Violin(datasets), Kde(data), Ecdf(data), Rugplot(data), Stripplot(datasets), Swarmplot(datasets)
2D grid Heatmap(data), Image(data), Pcolormesh(x, y, c), Histogram2D(x, y, bins), Contour(x, y, z), Contourf(x, y, z), Hexbin(x, y), Tricontour(x, y, z), Tripcolor(x, y, z)
Circular Pie(sizes, labels), Donut(sizes, labels)
Hierarchical Treemap(root), Sunburst(root), NestedPie(root) — all take TreeNode root
Flow Sankey(nodes, links) with SankeyNode[] and SankeyLink[]
Polar PolarPlot(r, θ), PolarScatter(r, θ), PolarBar(r, θ), PolarHeatmap(data, θBins, rBins), Radar(cats, vals)
Financial Candlestick(open, high, low, close, dates?), OhlcBar(open, high, low, close, dates?)
Pair-selection RelativeRotation(assetCloses, benchmarkCloses, labels) — an RRG chart: a 2D scatter of RS-Ratio against RS-Momentum, with a fading tail
3D Surface(x, y, z), Wireframe(x, y, z), Scatter3D(x, y, z), Stem3D(x, y, z), Bar3D(x, y, z), PlanarBar3D(x, y, z)
Field Quiver(x, y, u, v), Streamplot(x, y, u, v), Barbs(x, y, speed, dir), QuiverKey(x, y, u, label)
Special Gauge(value), ProgressBar(value), Sparkline(values), Bubble(x, y, sizes), Funnel(labels, values), Regression(x, y), Residplot(x, y), Pointplot(datasets), Spectrogram(signal), Table(cellData)

5. Configuring a series — common properties

The configure callback runs against the concrete series instance. The examples below show representative property sets:

// Line
ax.Plot(x, y, s =>
{
    s.Color = Colors.DodgerBlue;
    s.LineWidth = 2.0;
    s.LineStyle = LineStyle.Dashed;
    s.Marker = MarkerStyle.Circle;   // all 13 shapes supported (v1.7.2 Phase M):
                                      // Circle, Square, Triangle, TriangleDown/Left/Right,
                                      // Diamond, Pentagon, Hexagon, Star, Cross, Plus, None
    s.MarkerSize = 6;
    s.Smooth = true;                // cubic-spline smoothing
    s.Label = "Revenue";            // for legend
});

// Scatter
ax.Scatter(x, y, s =>
{
    s.Sizes = bubbleSizes;          // per-point size
    s.C = density;                  // per-point colormap value
    s.ColorMap = ColorMaps.Viridis;
    s.Alpha = 0.6;
});

// Bar
ax.Bar(cats, vals, s =>
{
    s.Color = Colors.SteelBlue;
    s.BarWidth = 0.7;
    s.ShowLabels = true;
    s.LabelFormat = "0.0";
    s.EdgeColor = Colors.Black;
    s.Orientation = BarOrientation.Horizontal;
});

// Pie
ax.Pie(sizes, labels, s =>
{
    s.Explode = [0, 0.1, 0, 0];
    s.AutoPct = "{0:F1}%";
    s.StartAngle = 90;
    s.Shadow = true;
});

// Heatmap / contour / surface
ax.Heatmap(data, s =>
{
    s.ColorMap = ColorMaps.Plasma;
    s.Normalizer = new LogNormalizer(1, 1000);
});

// Sankey
ax.Sankey(nodes, links, s =>
{
    s.NodeWidth = 24;
    s.NodePadding = 14;
    s.Iterations = 20;              // vertical-relaxation passes
    s.LinkColorMode = SankeyLinkColorMode.Gradient;
    s.InsideLabels = true;          // when NodeWidth is wide enough
});

6. Technical indicators — attach to a financial panel

After plotting a Candlestick, an OhlcBar or a price line, add:

ax.Candlestick(open, high, low, close)
  .Sma(20)
  .Ema(50, s => s.Color = Colors.Orange)
  .BollingerBands(period: 20, stdDev: 2.0)
  .Rsi(close, 14)
  .WilliamsR(high, low, close)
  .Obv(close, volume)
  .Cci(high, low, close, 20)
  .ParabolicSar(high, low);

The generic form is ax.Indicator(new MyIndicator(...)).


7. Annotations & references

ax.Annotate("Peak", x: 5.0, y: 12.3);
ax.Annotate("Crash", 6.0, 8.0, arrowX: 7.0, arrowY: 9.5);
ax.AxHLine(0);                                  // horizontal reference line
ax.AxVLine(Math.PI, c => c.Color = Colors.Red);
ax.AxHSpan(40, 60);                              // shaded horizontal band
ax.AxVSpan(DateTime.UtcNow.AddDays(-7), DateTime.UtcNow);
ax.BuyAt(x, y);                                 // trading signal marker
ax.SellAt(x, y);

// Threshold — dashed reference line + shaded breach span + optional label, one call
ax.Threshold(80.0, Orientation.Horizontal, ThresholdBreach.Above,
    color: Colors.Red, label: "Alarm");

Threshold(value, orientation, breach, color?, label?) composes an AxHLine/AxVLine at value, a SpanRegion covering the breach zone, and an optional label. It uses existing primitives; there is no new series or renderer.


8. 3-D scenes — camera, lighting, interactivity

Plt.Create()
   .WithSize(800, 600)
   .With3DRotation()                           // drag-to-rotate in SVG
   .AddSubPlot(1, 1, 1, ax => ax
       .Surface(xs, ys, zs, s => s.ColorMap = ColorMaps.Viridis)
       .WithCamera(elevation: 35, azimuth: -45, distance: 10)
       .WithLighting(dx: 0.3, dy: 0.3, dz: 1.0, ambient: 0.3, diffuse: 0.7)
       .SetZLabel("Altitude"))
   .Save("surface.svg");

distance sets the camera distance used by the perspective matrix. Lower values produce more foreshortening.


9. Minimal recipes — copy-paste starters

Line plot

Plt.Create().Plot(x, y).Save("line.svg");

Multi-panel dashboard

Plt.Create()
   .WithSize(1200, 800)
   .WithGridSpec(2, 2, heightRatios: [3, 1])
   .WithTitle("Q1 — ACME")
   .TightLayout()
   .AddSubPlot(1, 1, 1, ax => ax.Candlestick(o, h, l, c).Sma(20).BollingerBands(20, 2))
   .AddSubPlot(1, 1, 2, ax => ax.Bar(dates, volume).SetYLabel("Vol"))
   .AddSubPlot(1, 1, 3, ax => ax.Plot(dates, rsi).AxHLine(70).AxHLine(30))
   .Save("dashboard.svg");

Interactive Sankey

Plt.Create()
   .WithSize(1000, 600)
   .WithSankeyHover()
   .AddSubPlot(1, 1, 1, ax => ax
       .HideAllAxes()
       .Sankey(nodes, links, s =>
       {
           s.Iterations = 20;
           s.LinkColorMode = SankeyLinkColorMode.Gradient;
       }))
   .Save("flow.svg");

Nested pie

Plt.Create()
   .WithTitle("Revenue by department → product")
   .AddSubPlot(1, 1, 1, ax => ax.NestedPie(departments))
   .Save("nested.svg");

10. Where to look next

Clone this wiki locally