Logarithmic chart in FLOT
Asked Answered
S

4

13

Does anyone have any idea how to create a logarithmic chart in FLOT?

Basically I am trying to create a chart that looks like the one shown here (top left): http://leto.net/plot/examples/logarithms.html

However, I have given it a try using the same options but it doesn't show the chart the same way. I think there must have been a lot of changes to FLOT since then considering that the post is quite old.

If anyone has any idea, please do let me know.

Thanks.

Sike answered 16/11, 2011 at 23:58 Comment(0)
R
21

You can do this using the "transform" option on the yaxis.

See work here.

$(function () {
    // setup plot
    function sampleFunction(x1, x2, func) {
        var d = [ ];
        var step = (x2-x1)/300;
        for (var i = x1; i < x2; i += step )
            d.push([i, func( i ) ]);

        return d;
    }

    var options1 = {
        lines: { show: true },
        xaxis: { ticks: 4 },
        yaxis: { ticks: [0.001,0.01,0.1,1,10,100],
                 transform: function(v) {return Math.log(v+0.0001); /*move away from zero*/},
                 tickDecimals: 3 },
        grid: { hoverable: true, clickable: true, color: "#999" }
    };

    var data1 = sampleFunction( 0, 5, function(x){ return Math.exp(x)*Math.sin(x)*Math.sin(x) } );

    var plot1 = $.plot($("#chart1"),  [ { label: "exp(x)sin(x)^2", data: data1 } ], options1);
});

Full Working Code:

$(function () {
    // setup plot
    function sampleFunction(x1, x2, func) {
        var d = [ ];
        var step = (x2-x1)/300;
        for (var i = x1; i < x2; i += step )
            d.push([i, func( i ) ]);

        return d;
    }
    
    var options1 = {
        lines: { show: true  },
        xaxis: { ticks: 4 },
        yaxis: { ticks: [0.001,0.01,0.1,1,10,100],
                 transform:  function(v) {return Math.log(v+0.0001); /*move away from zero*/} , tickDecimals: 3 },
        grid: { hoverable: true, clickable: true , color: "#999"}
    };
    
    var data1 = sampleFunction( 0, 5, function(x){ return Math.exp(x)*Math.sin(x)*Math.sin(x) } );
    
    var plot1 = $.plot($("#chart1"),  [ { label: "exp(x)sin(x)^2", data: data1} ], options1);
    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js"></script>
<br/><br/>
<div id="chart1" style="width:600px;height:300px;"></div>
Rumor answered 17/11, 2011 at 16:22 Comment(5)
Thanks Mark. That's exactly what I wanted to achieve. It looks like this Math.log(v+0.0001); solves the problem that I had. I didnt have + 0.0001 and the graph just didnt want to draw properly.Sike
Thanks Mark. In order not to have to introduce a slight error, I would recommend replacing Math.log(v+0.0001) by v===0 ? null : Math.log(v) (flot won't display points for which v is null).Rendarender
@sacha, not sure how the axis would respond to a null value. I have this code in production and I actually modified it slightly: transform: function(v) { return v == 0 ? Math.log(0.00001) : Math.log(v) };Rumor
@Mark: When I tested it, flot simply didn't draw the point for which transform(v) returned null. The fix you have above works too for "everyday" values of v, but my point was that it assumes values for v that are typically much bigger that 0.00001, i.e. don't use this fix to plot functions where the observed variable is an inter-atomic distance measured in meters :)Rendarender
One important thing is missing: You will also need an "inverseTransform" function. Otherwise panning and zooming will break.Burck
O
5

Great work Mark

As the ticks of Y axis in Logarithmic graphs are in the format of power of 10,

I would like to share enhancement in Y axis ticks, Here it is.s

    $(function () {
    // setup plot
    function sampleFunction(x1, x2, func) {
        var d = [ ];
        var step = (x2-x1)/300;
        for (var i = x1; i < x2; i += step )
            d.push([i, func( i ) ]);

        return d;
    }

    var options1 = {
        lines: { show: true  },
        xaxis: { ticks: 4 },
        yaxis: { ticks: [0.001,0.01,0.1,1,10,100],
                 transform:  function(v) {return Math.log(v+0.0001); /*move away from zero*/} , tickDecimals: 3 ,
                 tickFormatter: function (v, axis) {return "10" + (Math.round( Math.log(v)/Math.LN10)).toString().sup();}
                },
        grid: { hoverable: true, clickable: true , color: "#999"}
    };

    var data1 = sampleFunction( 0, 5, function(x){ return Math.exp(x)*Math.sin(x)*Math.sin(x) } );

    var plot1 = $.plot($("#chart1"),  [ { label: "exp(x)sin(x)" + "2".sup(), data: data1} ], options1);
});

Please let me know if there is any better way.

Thanks.

Oe answered 3/2, 2012 at 7:17 Comment(0)
Z
2

As the other answerer said, good work Mark. There is a way to make your solution more robust.

Mark's answer will work for most cases, but the plot will not look right for values near or less than 0.0001. Also, you don't need to modify every value to move away from zero. I believe that flot tries to transform 0 to determine where the "bottom" of the plot should be. Because of this, you will not be able to make your plot axis limits dynamic. This will make your plots look very bad if your values are much greater than 0.0001. Therefore, the following modification makes Mark's solution more robust, but it requires knowing the minimum y value (ymin below) in your data.

var options1 = {
    lines: { show: true  },
    xaxis: { ticks: 4 },
    yaxis: { ticks: [0.001,0.01,0.1,1,10,100],
             transform:  Function("v","return v == 0 ? Math.log("+Math.pow(10,ymin)+") : Math.log(v);"), tickDecimals: 3 },
    grid: { hoverable: true, clickable: true , color: "#999"}
};
Zealand answered 2/9, 2014 at 14:2 Comment(0)
M
0

It is base 10. The approach it should not be?

transform: function (v) {
    if (v == 0) v = 0.0001;
    return Math.log(v) / Math.log(10);
},
inverseTransform: function (v) {
    Math.pow(10, v);
},
Monongahela answered 17/11, 2016 at 3:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.