Meilo
Meilo

Reputation: 3418

Avoid interference between multiple Matplotlib figures on the web

I have a page with multiple Matplotlib figures embedded. The figures get inserted/manipulated via Ajax as follows (with a time stamp in order to get reloaded by the browser):

<img src="/charts/somedata.png?time=' + str(time.time()) + '" />

The urls are then matched to a view like (I should mention that I use Django):

(r'^charts/(?P<chart>[A-Za-z_]+).png$', 'views.charts'),

def charts(request, chart):
    # Dynamically loading the appropriate module
    chart_module = import_module('functions.charts.' + chart)
    return chart_module.show_chart(request)

The chart modules (somedata.py) look like this:

from __future__ import division
from django.http import HttpResponseRedirect, HttpResponse

def show_chart(request):
    try:
        # Initiating figure
        from matplotlib.pyplot import figure
        from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
        fig1 = figure(figsize=(5.33,4), facecolor = 'white')
        ax = fig1.add_axes([0.02,0.02,0.98,0.98], aspect='equal')

        # Some plotting to ax

        canvas=FigureCanvas(fig1)
        response=HttpResponse(content_type='image/png')
        canvas.print_png(response)
        fig1.clear()
        return response

    except:
        return HttpResponseRedirect("/")

With matplotlib version 0.99.? I sometimes got the problem that part of one chart was drawn in another chart on the same page. Sometimes, that was fixed after a reload. The solution I came up with was to put the following in settings.py:

# Force matplotlib to NOT use any Xwindows backend.
# This is necessary before importing pyplot or anything else from matplotlib
import matplotlib
matplotlib.use('Agg')

However, after updating to matplotlib version 1.0.1, the problem is back. The figures interfere with each other, or parts of a figure are not drawn at all? Any ideas about where the problem could be?

EDIT: Example of two plots in one. The lines on top belong to another figure, where they are missing. I should also mention that this is never an issue running the development server locally! Oops: Something went wrong!

Upvotes: 3

Views: 2396

Answers (1)

Meilo
Meilo

Reputation: 3418

Moving the matplotlib import lines from settings.py to the top of each chart module as well as using savefig (as proposed by jozzas - thanks) seems to have solved the interference problem:

This was done by removing:

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
canvas=FigureCanvas(fig1)
canvas.print_png(response)

Then I added instead:

fig1.savefig(response, format='png')

UPDATE: The main issue was that the pyplot function did not correctly attach to the figure instance, which was discussed and solved in this post.

Upvotes: 1

Related Questions