Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ticks autoscaled when using imshow?

I am trying to change the value of the ticks on the x-axis an imshow plot using the following code:

import matplotlib.pyplot as plt
import numpy as np

def scale_xaxis(number):
    return(number+1001)

data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto')
ax.autoscale(False)
xticks = ax.get_xticks()
ax.xaxis.set_ticklabels(scale_xaxis(xticks))
plt.savefig("test.png")

Resulting image http://ubuntuone.com/2Y5ujtlEkEnrlTcVUxvWLU

However the x-ticks overlap and have "non-round" values. Is there some way for matplotlib to automatically do this? Either by using set_ticklabels or some other way?

like image 589
Magnus Avatar asked Nov 16 '12 01:11

Magnus


2 Answers

Also look into using extent (doc) to let matplotlib do all the thinking about how to put in the tick labels and add in an arbitrary shift:

data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto',extent=[10000,10010,0,1])  

If you definitely want do to it my hand, you might be better off setting the formatter and locator of the axis to get what you want (doc).

import matplotlib.pyplot as plt
import numpy as np

def scale_xaxis(number):
    return(number+1001)

def my_form(x,pos):
    return '%d'%scale_xaxis(x)

data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto')
ax.autoscale(False)
ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(int(2)))
ax.xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(my_form))

The locator needs to be set to make sure that ticks don't get put at non-integer locations which are then forcible cast to integers by the formatter (which would leave them in the wrong place)

related questions:

matplotlib: format axis offset-values to whole numbers or specific number

removing leading 0 from matplotlib tick label formatting

like image 88
tacaswell Avatar answered Sep 28 '22 00:09

tacaswell


There are several ways to do this.

You can:

  1. Pass in an array of ints instead of an array of floats
  2. Pass in an array of formatted strings
  3. Use a custom tick formatter

The last option is overkill for something this simple.

As an example of the first option, you'd change your scale_xaxis function to be something like this:

def scale_xaxis(numbers):
    return numbers.astype(int) + 1001

Note that what you're getting out of ax.get_xticks is a numpy array instead of a single value. Thus, we need to do number.astype(int) instead of int(number).

Alternately, we could return a series of formatted strings. set_xticklabels actually expects a sequence of strings:

def scale_xaxis(numbers):
    return ['{:0.0f}'.format(item + 1001) for item in numbers]

Using a custom tick formatter is overkill here, so I'll leave it out for the moment. It's quite handy in the right situation, though.

like image 30
Joe Kington Avatar answered Sep 28 '22 00:09

Joe Kington