Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to place a matplotlib plot into an html container using mpld3 and flask

I am trying to use the mpld3-flask example (https://github.com/nipunreddevil/mpld3-flask) as a template to achieve a certain behavior. What I would like, is to add links on the header bar to different plots, rather than having a radio button query form.

Right now, the example code above, in templates/index.html, makes a container and then populates it with a plot when the user submits a query by clicking the "View Plot" button. That happens in this code, as far as I can tell, in index.html:

$("#query").click(function() {  

  $("#loading-div-background").show();
  $("#container").hide();
  var plot_type = $('input:radio[name=plot_type]:checked').val();
  var qu = {"plot_type":plot_type}
  $.ajax({
    type: "POST",
    async:true,
    contentType: "application/json; charset=utf-8",
    url: "/query",
    data: JSON.stringify(qu),
    success: function (data) {     
     var graph = $("#container");
     graph.html(data);   
     $("#loading-div-background").hide();      
     $("#container").show();
   },
   dataType: "html"
 });
});

What I would like instead is to add to the header bar that currently has "Home" in it, and bring up each example plot in a different page. I would route to a different link, and then populate the template html code with the data for the plot, without requiring a user query.

I am a bit of a novice with html and essentially know nothing about JavaScript at this point. My sense here is that there is some relatively easy way to use flask + jinja2 to do this, but I haven't been able to figure it out.

I am having some trouble with the sort of unclear namespaces that result from combining all of these languages. I am usually very strict with namespaces in my own python programming (i.e. I never, ever use 'from ____ import *') so this is driving me a little crazy.

like image 831
Brian Hayden Avatar asked Sep 08 '14 16:09

Brian Hayden


People also ask

How do I transfer a Flask graph to HTML?

You need to create a route that connects to a send from directory invocation from Flask. So you basically create an image with a src attribute to your Flask route that sends the image using send_from_directory . That's to send from any arbitrary folder beyond the default static folder.

How do I show Matplotlib in HTML?

mpld3. show() converts any Matplotlib plot to HTML and opens the figure in the web browser.

What does mpld3 do?

The mpld3 project brings together Matplotlib, the popular Python-based graphing library, and D3js, the popular JavaScript library for creating interactive data visualizations for the web.


1 Answers

After working for a while, I have found a solution that seems to work and achieve the behavior I want. Note that I am using the twitter bootstrap css and javascript packages.

Basically, I make a button group:

  <div class="btn-group" data-toggle="buttons">
  <label class="btn btn-primary">
      <input type="radio" name="options" id="home"> Option 1
  </label>
  <label class="btn btn-primary">
      <input type="radio" name="options" id="option2"> Option 2
  </label>
  <label class="btn btn-primary">
      <input type="radio" name="options" id="option3"> Option 3
  </label>

Then in the javascript from the mpld3-flask example I use:

$('.btn-primary').on('click', function(){
  var qu = {"plot_type":$(this).find('input').attr('id')}
  $(this).addClass('active').siblings().removeClass('active');
  $.ajax({
    type: "POST",
    async:true,
    contentType: "application/json; charset=utf-8",
    url: "/query",
    data: JSON.stringify(qu),
    success: function (data) {
     var graph = $("#container");
     graph.html(data);
     $("#container").show();
     },
   dataType: "html"
  });  
}); 

Now I have a radio-button bar, with the currently active plot button set to 'active', which only requires one click on one of the buttons to draw a new plot.

EDIT: After learning more about flask and Jinja2, it is also easy to pass the mpld3-generated html to a a template, but there is a slight gotcha; it looks something like this

In the return of your python routing function:

return render_template('index.html', plot=mpld3_html)

Then in the html template you can reference this html with

{{plot|safe}}

Hope this helps someone else.

like image 61
Brian Hayden Avatar answered Sep 21 '22 00:09

Brian Hayden