Scatter Plot
Scatter plots can be created from two arrays containing X and Y values.
ScottPlot.Plot myPlot = new();
double[] xs = { 1, 2, 3, 4, 5 };
double[] ys = { 1, 4, 9, 16, 25 };
myPlot.Add.Scatter(xs, ys);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots can be created from a collection of Coordinates.
ScottPlot.Plot myPlot = new();
Coordinates[] coordinates =
{
new(1, 1),
new(2, 4),
new(3, 9),
new(4, 16),
new(5, 25),
};
myPlot.Add.Scatter(coordinates);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots can be created from any numeric data type, not just double.
ScottPlot.Plot myPlot = new();
float[] xs = { 1, 2, 3, 4, 5 };
int[] ys = { 1, 4, 9, 16, 25 };
myPlot.Add.Scatter(xs, ys);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots can be created from Lists, but be very cafeful not to add or remove items while a render is occurring or you may throw an index exception. See documentation about the Render Lock system for details.
ScottPlot.Plot myPlot = new();
List<double> xs = new() { 1, 2, 3, 4, 5 };
List<double> ys = new() { 1, 4, 9, 16, 25 };
myPlot.Add.Scatter(xs, ys);
myPlot.SavePng("demo.png", 400, 300);
The ScatterLine() method can be used to create a scatter plot with a line only (marker size is set to 0).
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] sin = Generate.Sin(51);
double[] cos = Generate.Cos(51);
myPlot.Add.ScatterLine(xs, sin);
myPlot.Add.ScatterLine(xs, cos);
myPlot.SavePng("demo.png", 400, 300);
The ScatterPoints() method can be used to create a scatter plot with markers only (line width is set to 0).
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] sin = Generate.Sin(51);
double[] cos = Generate.Cos(51);
myPlot.Add.ScatterPoints(xs, sin);
myPlot.Add.ScatterPoints(xs, cos);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots can be extensively styled by interacting with the object that is returned after a scatter plot is added. Assign text to a scatter plot’s Label property to allow it to appear in the legend.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys1 = Generate.Sin(51);
double[] ys2 = Generate.Cos(51);
var sp1 = myPlot.Add.Scatter(xs, ys1);
sp1.LegendText = "Sine";
sp1.LineWidth = 3;
sp1.Color = Colors.Magenta;
sp1.MarkerSize = 15;
var sp2 = myPlot.Add.Scatter(xs, ys2);
sp2.LegendText = "Cosine";
sp2.LineWidth = 2;
sp2.Color = Colors.Green;
sp2.MarkerSize = 10;
myPlot.ShowLegend();
myPlot.SavePng("demo.png", 400, 300);
Several line patterns are available
ScottPlot.Plot myPlot = new();
List<LinePattern> patterns = [];
patterns.AddRange(LinePattern.GetAllPatterns());
patterns.Add(new([2, 2, 5, 10], 0, "Custom"));
ScottPlot.Palettes.ColorblindFriendly palette = new();
for (int i = 0; i < patterns.Count; i++)
{
double yOffset = patterns.Count - i;
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51, offset: yOffset);
var sp = myPlot.Add.Scatter(xs, ys);
sp.LineWidth = 2;
sp.MarkerSize = 0;
sp.LinePattern = patterns[i];
sp.Color = palette.GetColor(i);
var txt = myPlot.Add.Text(patterns[i].Name, 51, yOffset);
txt.LabelFontColor = sp.Color;
txt.LabelFontSize = 22;
txt.LabelBold = true;
txt.LabelAlignment = Alignment.MiddleLeft;
}
myPlot.Axes.Margins(.05, .5, .05, .05);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots support generic data types, although double is typically the most performant.
ScottPlot.Plot myPlot = new();
int[] xs = { 1, 2, 3, 4, 5 };
float[] ys = { 1, 4, 9, 16, 25 };
myPlot.Add.Scatter(xs, ys);
myPlot.SavePng("demo.png", 400, 300);
A scatter plot may use DateTime units but be sure to setup the respective axis to display using DateTime format.
ScottPlot.Plot myPlot = new();
DateTime[] xs = Generate.ConsecutiveDays(100);
double[] ys = Generate.RandomWalk(xs.Length);
myPlot.Add.Scatter(xs, ys);
myPlot.Axes.DateTimeTicksBottom();
myPlot.SavePng("demo.png", 400, 300);
Scatter plots can be created using a step plot display where points are connected with right angles instead of diagnal lines. The direction of the steps can be customized.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(20);
double[] ys1 = Generate.Consecutive(20, first: 10);
double[] ys2 = Generate.Consecutive(20, first: 5);
double[] ys3 = Generate.Consecutive(20, first: 0);
var sp1 = myPlot.Add.Scatter(xs, ys1);
sp1.ConnectStyle = ConnectStyle.Straight;
sp1.LegendText = "Straight";
var sp2 = myPlot.Add.Scatter(xs, ys2);
sp2.ConnectStyle = ConnectStyle.StepHorizontal;
sp2.LegendText = "StepHorizontal";
var sp3 = myPlot.Add.Scatter(xs, ys3);
sp3.ConnectStyle = ConnectStyle.StepVertical;
sp3.LegendText = "StepVertical";
myPlot.ShowLegend();
myPlot.SavePng("demo.png", 400, 300);
NaN values in a scatter plot’s data will appear as gaps in the line.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
// long stretch of empty data
for (int i = 10; i < 20; i++)
ys[i] = double.NaN;
// single missing data point
ys[30] = double.NaN;
// single floating data point
for (int i = 35; i < 40; i++)
ys[i] = double.NaN;
for (int i = 40; i < 45; i++)
ys[i] = double.NaN;
myPlot.Add.Scatter(xs, ys);
myPlot.SavePng("demo.png", 400, 300);
Scatter plots draw straight lines between points by default, but setting the Smooth property allows the scatter plot to connect points with smooth lines. Lines are smoothed using cubic spline interpolation.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(10);
double[] ys = Generate.RandomSample(10, 5, 15);
var sp = myPlot.Add.Scatter(xs, ys);
sp.Smooth = true;
sp.LegendText = "Smooth";
sp.LineWidth = 2;
sp.MarkerSize = 10;
myPlot.SavePng("demo.png", 400, 300);
Tension of smooth lines can be adjusted for some smoothing strategies. Low tensions lead to ‘overshoot’ and high tensions produce curveswhich appear more like straight lines.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.RandomWalk(10);
double[] ys = Generate.RandomWalk(10);
var mk = myPlot.Add.Markers(xs, ys);
mk.MarkerShape = MarkerShape.OpenCircle;
mk.Color = Colors.Black;
double[] tensions = { 0.3, 0.5, 1.0, 3.0 };
foreach (double tension in tensions)
{
var sp = myPlot.Add.ScatterLine(xs, ys);
sp.Smooth = true;
sp.SmoothTension = tension;
sp.LegendText = $"Tension {tension}";
sp.LineWidth = 2;
}
myPlot.ShowLegend(Alignment.UpperLeft);
myPlot.SavePng("demo.png", 400, 300);
The quadratic half point path strategy allows scatter plots to be displayed with smooth lines connecting points, but lines are eased in and out of points so they never ‘overshoot’ the values vertically.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(10);
double[] ys = Generate.RandomSample(10, 5, 15);
var sp = myPlot.Add.Scatter(xs, ys);
sp.PathStrategy = new ScottPlot.PathStrategies.QuadHalfPoint();
sp.LegendText = "Smooth";
sp.LineWidth = 2;
sp.MarkerSize = 10;
myPlot.SavePng("demo.png", 400, 300);
Although a scatter plot may contain a very large amount of data, much of it may be unpopulated. The user can define min and max render indexes, and only values within that range will be displayed when the scatter plot is rendered.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var sp = myPlot.Add.Scatter(xs, ys);
sp.MinRenderIndex = 10;
sp.MaxRenderIndex = 40;
myPlot.SavePng("demo.png", 400, 300);
The area beneath a scatter plot can be filled.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var sp = myPlot.Add.Scatter(xs, ys);
sp.FillY = true;
sp.FillYColor = sp.Color.WithAlpha(.2);
myPlot.SavePng("demo.png", 400, 300);
The base of the fill can be defined.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var sp = myPlot.Add.Scatter(xs, ys);
sp.FillY = true;
sp.FillYColor = sp.Color.WithAlpha(.2);
sp.FillYValue = 0.6;
myPlot.SavePng("demo.png", 400, 300);
Filled areas above and below the FillY value can be individually customized
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var sp = myPlot.Add.Scatter(xs, ys);
sp.FillY = true;
sp.FillYValue = 0;
sp.FillYAboveColor = Colors.Green.WithAlpha(.2);
sp.FillYBelowColor = Colors.Red.WithAlpha(.2);
myPlot.SavePng("demo.png", 400, 300);
The area beneath a scatter plot can be filled with a custom gradient of colors.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var poly = myPlot.Add.ScatterLine(xs, ys);
poly.FillY = true;
// colors are placed at specific positions on the X axis
poly.AxisGradientDirection = AxisGradientDirection.Horizontal;
poly.ColorPositions.Add(new(Colors.Red, 0));
poly.ColorPositions.Add(new(Colors.Orange, 10));
poly.ColorPositions.Add(new(Colors.Yellow, 20));
poly.ColorPositions.Add(new(Colors.Green, 30));
poly.ColorPositions.Add(new(Colors.Blue, 40));
poly.ColorPositions.Add(new(Colors.Violet, 50));
myPlot.SavePng("demo.png", 400, 300);
Scatter plots may be filled with vertical gradients.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var poly = myPlot.Add.ScatterLine(xs, ys);
poly.FillY = true;
// colors are placed at specific positions on the Y axis
poly.AxisGradientDirection = AxisGradientDirection.Vertical;
poly.ColorPositions.Add(new(Colors.Red, -1));
poly.ColorPositions.Add(new(Colors.Blue, 0));
poly.ColorPositions.Add(new(Colors.Orange, .5));
poly.ColorPositions.Add(new(Colors.Magenta, 1));
myPlot.SavePng("demo.png", 400, 300);
Scatter plot points can be multiplied by custom X and Y scale factors, or shifted horizontally or vertically using X and Y offset values.
ScottPlot.Plot myPlot = new();
double[] xs = Generate.Consecutive(51);
double[] ys = Generate.Sin(51);
var sp = myPlot.Add.Scatter(xs, ys);
sp.ScaleX = 100;
sp.ScaleY = 10;
sp.OffsetX = 500;
sp.OffsetY = 5;
myPlot.SavePng("demo.png", 400, 300);
A stacked filled line plot effect can be achieved by overlapping ScatterLines that fill area.
ScottPlot.Plot myPlot = new();
// create sample data
double[] xs = { 1, 2, 3, 4 };
double[] ys1 = { 1, 3, 1, 2 };
double[] ys2 = { 3, 7, 3, 1 };
double[] ys3 = { 5, 2, 5, 6 };
// shift each plot vertically by the sum of all plots before it
ys2 = Enumerable.Range(0, ys2.Length).Select(x => ys2[x] + ys1[x]).ToArray();
ys3 = Enumerable.Range(0, ys2.Length).Select(x => ys3[x] + ys2[x]).ToArray();
// plot the padded data points as ScatterLine
var sp3 = myPlot.Add.ScatterLine(xs, ys3, Colors.Black);
var sp2 = myPlot.Add.ScatterLine(xs, ys2, Colors.Black);
var sp1 = myPlot.Add.ScatterLine(xs, ys1, Colors.Black);
// set plot style
sp1.LineWidth = 2;
sp2.LineWidth = 2;
sp3.LineWidth = 2;
sp1.FillY = true;
sp2.FillY = true;
sp3.FillY = true;
sp1.FillYColor = Colors.Green;
sp2.FillYColor = Colors.Orange;
sp3.FillYColor = Colors.Blue;
// use tight margins so data goes to the edge of the plot
myPlot.Axes.Margins(0, 0, 0, 0.1);
myPlot.SavePng("demo.png", 400, 300);
Demonstrates how to combine filled scatter plots with vertical and horizontal offsets to achieve an interesting visual effect.
ScottPlot.Plot myPlot = new();
double[] xs = ScottPlot.Generate.Consecutive(100);
ScottPlot.Colormaps.MellowRainbow cmap = new();
for (int i = 0; i < 10; i++)
{
double yOffset = 9 - i * 0.5;
double[] ys = Generate.Sigmoidal(xs.Length)
.Select(y => y + yOffset)
.ToArray();
Generate.AddNoiseInPlace(ys, 0.1);
var sig = myPlot.Add.ScatterLine(xs, ys);
sig.LineColor = Colors.Black;
sig.LineWidth = 1.5f;
sig.FillY = true;
sig.FillYValue = yOffset;
sig.FillYAboveColor = cmap.GetColor(i, 10);
}
myPlot.HideGrid();
myPlot.Axes.MarginsX(0);
myPlot.SavePng("demo.png", 400, 300);























