question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ticks: improve positions of log-scaled minor ticks

See original GitHub issue

@at2software recently asked about support for logarithmic scaling in ScottPlot. While much of ScottPlot is hard-coded to assume linear axes, it may be possible to create convincing scatter plots of log-scaled data. This issue tracks progress toward exploring these options now that the library has matured since it was last considered. Related: #29, #41, #207, #412

Present Capabilities

ScottPlot is really close to being able to create convincing log-scaled scatter plots already. The only giveaway is that the connecting lines between scatter points are straight and not curved. EDIT: this is pretty close to what the same code looks like in Python

double[] xs = { 1, 2, 3, 4, 5 };
double[] ys = { 10, 2_000, 50_000, 1_000_000, 1_500_000 };

var plt = new ScottPlot.Plot(500, 300);

// Plot the log of the Ys
double[] logYs = ys.Select(y => Math.Log10(y)).ToArray();
plt.AddScatter(xs, logYs);

// Use a custom tick formatter to label tick marks as the antilog of their position
Func<double, string> tickLabeler = (y) => Math.Pow(10, y).ToString("N0");
plt.YAxis.TickLabelFormat(tickLabeler);

// Use log-spaced tick marks and grid lines to make it more convincing
plt.YAxis.MinorGrid(enable: true);
plt.YAxis.MinorLogScale(true);

// Set the axis limits manually to ensure edges terminate at a nice locations in log space
plt.SetAxisLimits(.5, 5.5, 0, Math.Log10(10_000_000));
plt.SaveFig("log.png");

image

Python/Matplotlib Example

import matplotlib.pyplot as plt

xs = [ 1, 2, 3, 4, 5 ]
ys = [ 10, 2_000, 50_000, 1_000_000, 1_500_000 ]

plt.semilogy()
plt.plot(xs, ys, '.-', ms=10)

plt.grid(True, 'major', alpha=1)
plt.grid(True, 'minor', alpha=.2)
plt.show()

log

outdated details about connecting lines ## Special Log-Scaled Scatter Plot Type?

Could a custom plot type be made that replaces these straight lines with a function that dynamically calculates the log-scaled Y pixel for each X position of a connecting line between each pair of points in a scatter plot? We could borrow some logic from function plots:

https://github.com/ScottPlot/ScottPlot/blob/9b4aaa273890f0d0f66474cd21173417fac21aed/src/ScottPlot/Plottable/FunctionPlot.cs#L54-L81

I’m inclined to experiment in a new plot type to allow free experimentation (with breaking API changes along the way) until this idea is fleshed-out, then we could consider merging it into the existing ScatterPlot type.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
swhardencommented, Oct 20, 2021

I would look to avoid creating a new plot type, especially if the existing problems are more about the ticks and axis, not the portable

Good point! This may be bad practice so I’ll be more mindful not to do it in the future, but I significantly edited the content of the original comment from what it was originally. Originally my thinking was that scatter plot connecting lines should be curved in log-scale mode (not straight lines), but after more consideration/research I realized it already behaves like matplotlib so the plot type doesn’t need changing, but instead the primary issue is the minor tick position 👍

All that said, your note that branching-off new plot type with slightly varied behavior leads to a more confusing API is very well received!

0reactions
swhardencommented, Oct 21, 2021

I think this is fully fixed now 😎

logscale2

[Test]
public void Test_LogAxis_Y_B()
{
    double[] xs = { 1, 2, 3, 4, 5 };
    double[] ys = { 10, 2_000, 50_000, 1_000_000, 1_500_000 };

    var plt = new ScottPlot.Plot(600, 600);

    // Plot the log of the Ys
    double[] logYs = ys.Select(y => Math.Log10(y)).ToArray();
    var scatter = plt.AddScatter(xs, logYs);

    // label each point with a red line
    plt.Palette = ScottPlot.Palette.ColorblindFriendly;
    for (int i = 0; i < scatter.PointCount; i++)
    {
        double x = scatter.Xs[i];
        double y = scatter.Ys[i];
        double actualY = Math.Pow(10, y);
        var color = plt.Palette.GetColor(i);
        plt.AddHorizontalLine(y, color, 1, ScottPlot.LineStyle.Dot);
        plt.AddVerticalLine(x, color, 1, ScottPlot.LineStyle.Dot);
        plt.AddPoint(x, y, color, 10, ScottPlot.MarkerShape.openCircle);
        var txt = plt.AddText(actualY.ToString("N0"), x, y, 12, System.Drawing.Color.Black);
    }

    // Use a custom tick formatter to label tick marks as the antilog of their position
    Func<double, string> tickLabeler = (y) => Math.Pow(10, y).ToString("N0");
    plt.YAxis.TickLabelFormat(tickLabeler);

    // Use log-spaced tick marks and grid lines to make it more convincing
    plt.YAxis.MajorGrid(enable: true);
    plt.YAxis.MinorGrid(enable: true);
    plt.YAxis.MinorLogScale(true);

    // Set the axis limits manually to ensure edges terminate at a nice locations in log space
    plt.SetAxisLimits(0, 6, 0, Math.Log10(10_000_000));

    TestTools.SaveFig(plt);

    // Show the actual Y values used for tick marks
    foreach (ScottPlot.Ticks.Tick tick in plt.YAxis.GetTicks())
        Console.WriteLine(tick);
}

image

Read more comments on GitHub >

github_iconTop Results From Across the Web

Matplotlib semi-log plot: minor tick marks are gone when ...
When making a semi-log plot (y is log), the minor tick marks (8 in a decade) on the y axis appear automatically, but...
Read more >
How to show minor tick labels on a log-scale with Matplotlib
Change the appearance of ticks and tick label using ick_params() method. Set the minor axis formatter with format strings to format the tick....
Read more >
Major and minor ticks — Matplotlib 3.7.2 documentation
Minor ticks are off by default (using NullLocator and NullFormatter ). Minor ticks can be turned on without labels by setting the minor...
Read more >
What are the labels for minor ticks in a log scale graph?
What are the labels for the minor ticks in a log scale graph? enter image description here. I would like to label them....
Read more >
Setting minor ticks with log scale axis PGFPlots
You could add extra x ticks={30,40,60,70,80,90,300,400,600,700,800,900,2000,3000,4000}, extra tick style={grid=minor} to the axis options but ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found