Skip to content

Fluent Cheatsheet

H.P. Gansevoort edited this page Jul 4, 2026 · 11 revisions

Fluent API Cheat Sheet

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. Start fluent construction.
Plt.Figure(width, height) Figure Direct model (skip the builder). Rarely used.
Plt.Mosaic("AB;CC", ...) MosaicFigureBuilder Subplot layout from an ASCII-art string.
Plt.Style.Use(...) void Apply a global stylesheet (e.g. "seaborn").
Plt.Style.Context(...) StyleContext Scoped style override (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()InteractiveExtensions.Show(Figure) was removed in v1.13.0 in favor of the async-only surface above. Calling anything on the handle after it is disposed throws ObjectDisposedException.

Figure-level series shortcuts (bypass AddSubPlot)

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");

Supported families at figure level: Plot / Scatter / Bar / Hist / Pie / Image / Heatmap / Treemap / Sunburst / Sankey / Surface / Scatter3D / Bar3D / PolarPlot / Candlestick / OhlcBar / BoxPlot / Violin / 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: 11 inside (UpperRight, UpperLeft, LowerRight, LowerLeft, Right, CenterLeft, CenterRight, LowerCenter, UpperCenter, Center, Best) + 4 outside (OutsideRight, OutsideLeft, OutsideTop, OutsideBottom — reserved by constrained layout).

Order-independent WithLegend (v1.13.0 fix): WithLegend(position, visible) used to wholesale-replace the Legend record, silently dropping any earlier WithLegendValues() / WithLegend(configure) call. It now only updates Visible and Position, preserving every other property regardless of call order — .WithLegendValues().WithLegend(LegendPosition.UpperRight) and .WithLegend(LegendPosition.UpperRight).WithLegendValues() are equivalent.

LegendValues last-value suffix: WithLegendValues(enabled: true) appends each labelled XYSeries' last data value to its legend entry (e.g. SignalSignal = 2.70, invariant culture F2). Non-XY series display the label text only. Default false — byte-identical legend output when unused.

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 expressed as fractions (0-1) of the parent axes. AddInset(InsetBounds, configure) is the canonical overload; the double-argument convenience overload just constructs an InsetBounds and forwards.

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), 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 + offset)
Categorical Bar(cats, vals), 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) — RRG: RS-Ratio × RS-Momentum 2D scatter with 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, so IntelliSense shows everything. Representative 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 Candlestick / OhlcBar / 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);

Generic: 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 with a SpanRegion covering the breach zone (ThresholdBreach.Above/Below, extending to the axis bound) plus an optional label Annotation — no new series or renderer, just the existing primitives wired together.


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 controls camera distance for 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