Skip to content
H.P. Gansevoort edited this page Oct 30, 2026 · 94 revisions

MatPlotLibNet Wiki

Matplotlib-inspired charting for .NET. MatPlotLibNet renders charts on the server as SVG, PNG, PDF or animated GIF. It ships an MCP server, so an AI agent can render charts with it. It has 91 series types, twenty-six charts built from them in one call, 13 map projections with embedded Natural Earth data, 30 themes, LaTeX-style MathText, O(1) streaming (57 of its 59 technical indicators have a streaming form), a control room (Plt.OpsDashboard(): KPI tiles, state timelines, a service-topology panel and one shared trend window), and native controls for Blazor, WPF, MAUI, Avalonia, Uno and ASP.NET Core. The API is fluent and works with dependency injection. There is no JavaScript framework, no WebView and no SaaS.

1.27.0 is the current release, and it finishes the roadmap. A word cloud, a chord diagram, a ternary plot and a Piper diagram are new charts, a brush on one chart lights the same rows on the others, and an animation can be saved as one SVG with a slider and a play button that needs no server. A live chart sends its own gestures, one IChartEventHandler receives everything a viewer does on a server or on a native control, and several viewers of one chart share it by design, each with a named pointer. Home goes back to the view the chart started with, a finger works the MAUI chart, and the Windows heads are built and tested by CI. 57 of the 59 indicators have a streaming form that follows each new bar, and transfer entropy follows a window with the Kraskov estimate. Every new call is shown in code on the examples page.

1.26.0 gave marks that are a size in data units a home: a waffle chart counts "37 of every 100" in squares, a calendar of events puts a mark in the cell of each day, and Point and Figure, Renko and Kagi charts draw a price as boxes, bricks and a line that thickens and thins, without a time axis. A fill can fade from one colour to another, an arrow can follow a connected scatter, a spine can span only the data's range, and SetAspect keeps an equal scale. An icicle chart, an arc diagram and a stem-and-leaf plot join the layouts, a waterfall can mark a target on each bar, parallel coordinates carry a scale on every column, and the comparison with matplotlib now runs in CI. Every new call is shown in code on the examples page.

1.25.0 gave each value a chart works out one owner that every reader asks: a colour bar puts its ticks where the chart's normaliser puts the colours, a theme owns the neutral grey that reference lines and outlines wear, a grid you changed with WithGrid stays a change over whichever theme the figure is drawn under, an inset is built where it stands, the ambient and diffuse strength of a light reach the surfaces and bars it lights, and a relative rotation graph always shows its centre. Save("chart.png") without the Skia package is refused instead of writing SVG under a raster name. The statistics grew too: ProbabilityPlot draws a Q-Q plot against an exponential, uniform, log-normal or Student t distribution, RiskTable writes the number at risk and the log-rank test under a survival curve, ShewhartChart draws the other control charts and flags Nelson's eight tests, and Vwap can be anchored at a bar and VolumeProfile shows where the volume traded. A violin is drawn from the Gaussian density, and the tables of a Marimekko chart and a calendar heatmap name their columns and their dates. Every new call is shown in code on the examples page.

1.24.0 let a chart carry any number of Y axes. Every Y axis of a chart now belongs to one container, so a chart can have as many as it needs: WithAddRightYAxis and WithAddLeftYAxis each stack one more axis on their side, with its own range, ticks, colour, series and legend entry, and the four scales 1.23.0 stopped at are no limit any more. The older second-axis verbs keep working and are marked obsolete. A Y axis title stands the same distance from its tick labels on the left and on the right, 4 px by default, and WithYAxisTitleGap sets another; the left title no longer runs off the edge of the figure. The MCP server checks every axis of a chart spec, and one event that fails no longer ends a live chart's session. Thirteen more rows of the roadmap are done in the same release: colour bar ticks at round numbers, one radial scale for polar charts, polar bars that stack, bars stacked on both sides of zero, a filled contour that follows its limits, the layers of a stack plot named in the legend, series refused when they are built and not when they are drawn, and maps that are coloured by a value, carry points, bubbles, hexagon bins, flows, a cartogram and a Dorling map, and come back from JSON. Every new call is shown in code on the examples page.

1.23.0 let a chart carry a third and a fourth Y axis, two to a side, and moved the technical indicators that read a candle's open, high, low, close and volume from separate array parameters to one OhlcvBars value. A series on a second axis keeps any kind through JSON, and zoom, pan and Home move every stacked axis' own range. Its calls are on the examples page.

1.22.0 let several series share one colour from the theme's cycle instead of each taking the next one. A Kaplan-Meier curve draws a confidence band and censor marks in its own colour, and two new verbs use the same mechanism: Raincloud (a half violin, a box and a group's raw points in one colour) and Horizon (a signed series folded into bands of two hues). Every new call is shown in code on the examples page.

1.21.0 made every chart type and every axes setting come back from JSON as itself. A treemap's, sunburst's, dendrogram's and clustermap's trees, a Sankey's nodes and links, a polar chart's data, a tree grid's rows, a streaming chart's current points and a planar 3-D bar's data all used to come back as a placeholder or a plain series; the MCP server lists and accepts all eight chart types it had refused by name. An axes' Z axis, its 3-D pane colours and its tooltip switch now travel through JSON too. The one series this release does not reach is MatPlotLibNet.Geo's GeoPolygonSeries, whose projection needed a wire shape of its own first; 1.24.0 gave it one. Every fix is shown in code on the examples page.

1.20.0 gave fifteen charts that took a page of code one call each on the axes builder: Pareto, Ridgeline, CalendarHeatmap, QQPlot, ControlChart, KaplanMeier, StreamGraph, Marimekko, Spy and six more take the data as you hold it (names, groups, samples, dates, a matrix) and build the chart from the series the library already has. Underneath them, a figure written to JSON came back as the picture it was, its theme and a colour map built in code included, so the MCP server and every transport carry it whole. NaN is the one missing value: a line breaks at a gap, as in matplotlib, and nothing is drawn at NaN. Bars on a log axis reach the bottom edge, horizontal bars lie along their values, a waterfall marks its totals, and WithDpi and SaveOptions reach the file. Its calls are shown in code on the examples page.

1.19.0 let a line carry its name at its end, in its own colour, instead of in the legend (WithDirectLabel()), and SetYAxisColor / SetXAxisColor colour an axis to match its line in one call, on the left, bottom, right and top axis alike. The right-hand and top axes take their own tick settings, get room of their own in the layout and keep their colours through JSON, and a line on them hides when its legend entry is clicked and reports values in its own axis' units when the line itself is clicked. Its calls are on the examples page.

1.18.2 made a state timeline answer the pointer: hovering a segment names the event and the stretch it covers, clicking it tells your application which segment it was, and a reference line can be moved after it is drawn, which is what a playback marker needs. Dragging now pans a chart that scales itself, which did nothing until the first zoom; a timeline pans and zooms along time only; and stacked charts that share an X axis move together. The WPF chart control also keeps panning and zooming the figure it was last handed, where before it went on acting on the first one, and the package says which Windows version a project has to target to use it. There is a complete WPF example of a replay timeline.

NuGet · Changelog · License: MIT

dotnet add package MatPlotLibNet
using MatPlotLibNet;

double[] x = [1, 2, 3, 4, 5];
double[] y = [2, 4, 3, 5, 1];

Plt.Create()
   .AddSubPlot(1, 1, 1, ax => ax.Plot(x, y, s => s.Label = "signal"))
   .Save("chart.svg");

Start here

Page For
Getting Started install, first chart, output formats, subplots
Fluent Cheatsheet one page: Plt · FigureBuilder · AxesBuilder
Examples what each release added, in code that compiles
Chart Types all 91 series with code — including the control room and the charts in one call
Package Map which of the 14 NuGet + 3 npm packages you need
Styling · MatplotlibThemes themes, colours, fonts, layout
Advanced animation, geo projections, MathText, DI
Streaming live data, O(1) ring buffers, indicators
Bidirectional SignalR push charts to Blazor / Angular / React / Vue
Interactive Controls · Keyboard Shortcuts pan, zoom, brush-select, hotkeys
Notebooks Polyglot / Jupyter
Accessibility The data table beside the chart, ARIA, contrast, screen readers
Benchmarks render and export timings
Roadmap · Contributing what is done and what is still to come, how to help

Also: Playground · From matplotlib to C# · Cookbook · API Reference.

Who it is for

You are… You get…
Blazor / ASP.NET Core <MplChart> and <MplLiveChart>, SignalR push, a REST endpoint — wired with standard DI
WPF / MAUI / Avalonia / Uno native controls, no WebView: the WPF, Avalonia and Uno controls draw through SkiaSharp and the MAUI view through Microsoft.Maui.Graphics, and all four pan, zoom and brush-select, by mouse or by finger
Data scientist inline SVG in notebooks, plotting straight from Microsoft.Data.Analysis.DataFrame
Trading / finance candlestick, OHLC, 59 indicators, drawing tools, backtest panels, RRG
Ops / control room Plt.OpsDashboard() — KPI tiles, state timelines, a service-topology panel, one shared trend window
Backend / headless render SVG, PNG, PDF or GIF server-side with zero UI dependencies
Angular / React / Vue TypeScript clients on the same hub and the same chart definitions

What it is not

MatPlotLibNet is not a JavaScript wrapper, not a WebView host and not a hosted service. Charts are built and rendered in .NET. Only a picture or a chart definition leaves the process.

Quality bar

Every class passes a strict per-class coverage gate of at least 90 % line and branch coverage. That is currently 1,094 classes at 99.8 % line and 98.8 % branch coverage, across 25,667 tests. A separate fidelity suite compares rendering with images drawn by matplotlib; it runs in CI.

If you have a question or something is missing, open a Discussion or an Issue. Releases follow what people actually need.

Clone this wiki locally