Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

axes.fmt_xdata in matplotlib not being called

I'm trying to format my X axis dates in a Django application where I'm returning the graph in memory in a response object. I followed the same example that I already use in an ipython notebook, and do this:

def pretty_date(date):
    log.info("HELLO!")
    return date.strftime("%c")

def image_calls(request):
    log.info("in image_loadavg")

    datetimes = []
    calls = []
    for m in TugMetrics.objects.all():
        datetimes.append(m.stamp)
        calls.append(m.active_calls)

    plt.plot(datetimes, calls, 'b-o')
    plt.grid(True)
    plt.title("Active calls")
    plt.ylabel("Calls")
    plt.xlabel("Time")

    fig = plt.gcf()
    fig.set_size_inches(8, 6)
    fig.autofmt_xdate()

    axes = plt.gca()
    #axes.fmt_xdata = mdates.DateFormatter("%w %H:%M:%S")
    axes.fmt_xdata = pretty_date

    buf = io.BytesIO()
    fig.savefig(buf, format='png', dpi=100)
    buf.seek(0)
    return HttpResponse(buf, content_type='image/png')

The graph is returned but I seem to have no control over how to X axis looks, and my HELLO! log is never called. Note that the m.stamp is a datetime object.

This works fine in ipython notebook, both running matplotlib 1.4.2.

Help appreciated.

like image 959
Michael Soulier Avatar asked Feb 16 '15 01:02

Michael Soulier


People also ask

Why is matplotlib not showing plot?

The issue actually stems from the matplotlib backend not being properly set, or from a missing dependency when compiling and installing matplotlib.

How do I swap axes in matplotlib?

To switch axes in matplotlib, we can create a figure and add two subplots using subplots() method. Plot curves, extract x and y data, and set these data in a second plotted curve.


1 Answers

axes.fmt_xdata controls the coordinates that are interactively displayed in the lower right-hand corner of the toolbar when you mouse over the plot. It's never being called because you're not making an interactive plot using a gui backend.

What you want is ax.xaxis.set_major_formatter(formatter). Also, if you'd just like a default date formatter, you can use ax.xaxis_date().

As a quick example based on your code (with random data):

import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

time = mdates.drange(dt.datetime(2014, 12, 20), dt.datetime(2015, 1, 2),
                     dt.timedelta(hours=2))
y = np.random.normal(0, 1, time.size).cumsum()
y -= y.min()

fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(time, y, 'bo-')
ax.set(title='Active Calls', ylabel='Calls', xlabel='Time')
ax.grid()

ax.xaxis.set_major_formatter(mdates.DateFormatter("%w %H:%M:%S"))
fig.autofmt_xdate() # In this case, it just rotates the tick labels

plt.show()

enter image description here

And if you'd prefer the default date formatter:

import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

time = mdates.drange(dt.datetime(2014, 12, 20), dt.datetime(2015, 1, 2),
                     dt.timedelta(hours=2))
y = np.random.normal(0, 1, time.size).cumsum()
y -= y.min()

fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(time, y, 'bo-')
ax.set(title='Active Calls', ylabel='Calls', xlabel='Time')
ax.grid()

ax.xaxis_date() # Default date formatter
fig.autofmt_xdate()

plt.show()

enter image description here

like image 182
Joe Kington Avatar answered Sep 18 '22 01:09

Joe Kington