niloch / iplotter

JavaScript charting in ipython/jupyter notebooks -
http://niloch.github.io/iplotter/
MIT License
85 stars 10 forks source link

Google Charts Gauge #5

Closed loosak closed 7 years ago

loosak commented 8 years ago

Hello,

I try to create gauge charts from examples and nothing is shown. Other chart (Pie) is working perfectly for same.

Here is my code:

from iplotter import GCPlotter

plotter = GCPlotter()

data = [
        ['label', 'value'],
        ['Memory', 80],
        ['CPU', 55],
        ['Network', 68]
]

options = {
     'width':  784,
     'height': 400,
     'redFrom': 90, 
     'redTo': 100,
     'yellowFrom': 75, 
     'yellowTo': 90,
     'minorTicks': 5
}

plotter.plot(data, 'Gauge', options)

Thanks

niloch commented 8 years ago

Google Charts are complicated because different plot types may need different javascript packages to be loaded.

Several basic plot types use the same package ,google.charts.load('current', {'packages':['corechart']});, such as Scatter, Bar, Pie, Line. More advanced charts use a different package for each one and they have different naming conventions for the chart object (sometimes they drop the Chart suffix of the name). The Gauge uses google.charts.load('current', {'packages':['gauge']});.

We might be able to have a dictionary lookup using the chart_type keyword argument to match which package needs to be loaded in the iframe. We'll need to see how much extra complexity this might add before we change anything.

In the mean time you can use the following:

from iplotter import GCPlotter

plotter = GCPlotter()

plotter.template = '''
<div id={{div_id}} style='width: 100%; height: 100%' ></div>
        <script type='text/javascript'>
                google.charts.load('current', {'packages':['gauge']});
                google.charts.setOnLoadCallback(drawChart);

                function drawChart() {
                    var data = google.visualization.arrayToDataTable({{data}});

                    var chart = new google.visualization.{{chart_type|title}}(document.getElementById('{{div_id}}'));

                    chart.draw(data, {{options}});
                }
        </script>
'''
hakanjonsson commented 7 years ago

iplotter is great, but unfortunately I have the same problem as @loosak . I tried the workaround you suggest, but I just get a blank frame in the notebook. I even tried setting the data explicitly in the drawChart function, like in the Google Chart example code, but with the same result. The core charts, for example Column chart, works fine and displays correctly. Is there anything special about the non-core package charts?

niloch commented 7 years ago

Hmm. Overriding the plotter.template attribute with the string above followed by plotter.plot(data, 'Gauge', options) works for me. I tested with both python 2 and python 3.

You can try saving your plot to an HTML file and opening it in the browser and looking at the Javascript console for errors.

The core chart package is loaded by default. We could load them all by default, or we could add a parameter specifying which chart package to load.

I am open to both. We'll need to test if loading them all doesn't impact performance

hakanjonsson commented 7 years ago

Gauge worked for me now as well. Don't think I changed anything. However, my original problem was with Sankey diagrams. Finally got that working too, by setting data = [], and then adding columns and values in the drawChart method: data.addColumn('string', 'From'); data.addColumn('string', 'To'); data.addColumn('number', 'Weight'); data.addRows([ ['S', 'T', 60805], ['S', 'F', 4965], ['T', 'TT', 52324], ['T', 'TF', 8481]]) However, I need to be able to set data dynamically rather than hardcoded in the drawchart. I tried setting data = [['S', 'T', 60805],['S', 'F', 4965],['T', 'TT', 52324],['T', 'TF', 8481]]

and add columns only in drawChart: data.addColumn('string', 'From'); data.addColumn('string', 'To'); data.addColumn('number', 'Weight'); , but that did not work. The console reported this errors in this case: Uncaught Error: Unknown header type: 60805 at https://www.gstatic.com/charts/45/js/jsapi_compiled_default_module.js:23:258 at Array.map (native) at gvjs_v (https://www.gstatic.com/charts/45/js/jsapi_compiled_format_module.js:24:307) at gvjs_rba (https://www.gstatic.com/charts/45/js/jsapi_compiled_default_module.js:23:172) at Object.gvjs_Tl [as arrayToDataTable] (https://www.gstatic.com/charts/45/js/jsapi_compiled_default_module.js:25:305) at drawChart (about:srcdoc:11:53) at Object.google.a.c.xc (https://www.gstatic.com/charts/loader.js:152:318) at Object.google.a.c.Na (https://www.gstatic.com/charts/loader.js:152:127) at f (https://www.gstatic.com/charts/loader.js:149:317) at Object.google.a.b.Ob (https://www.gstatic.com/charts/45/loader.js:49:281) Any suggestions?

niloch commented 7 years ago

Using DataTable with addColumn and addRows is equivalent to arrayToDataTable. So the first row of data should be ["From", "To", "Weight"].

The following example works


from iplotter import GCPlotter

plotter= GCPlotter()

plotter.template = '''
<div id={{div_id}} style='width: 100%; height: 100%' ></div>
    <script type='text/javascript'>
        google.charts.load('current', {'packages':['sankey']});
        google.charts.setOnLoadCallback(drawChart);

        function drawChart() {
            var data = google.visualization.arrayToDataTable({{data}});

            var chart = new google.visualization.{{chart_type|title}}(document.getElementById('{{div_id}}'));

            chart.draw(data, {{options}});
        }
    </script>
'''

data =[
        ['From', 'To', 'Weight'],
        ['S', 'T', 60805],
        ['S', 'F', 4965],
        ['T', 'TT', 52324],
        ['T', 'TF', 8481]
    ]

plotter.plot(data, "Sankey")