1

If the following code is run

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))
plt.imshow(a, cmap='Reds', interpolation='nearest')
plt.savefig('fig.png',bbox_inches='tight')

I got the picture below, with all the cells representing each random number.

enter image description here

However, when the axis is added as the code shown below:

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))
plt.imshow(a, cmap='Reds', interpolation='nearest')

plt.xlim(0, 10)
plt.xticks(list(range(0, 10)))
plt.ylim(0, 10)
plt.yticks(list(range(0, 10)))

plt.savefig('fig3.png',bbox_inches='tight')

I got the picture with less resolution:

enter image description here

So how can I add axis ticks without affecting the resolution? If this is related to the font size of axis markers, how to automatically adjust them so as to keep the original resolution?

2
  • Thanks, but how to label 100 as 1, 200 as 2, ...., 1000 as 10? Commented Dec 16, 2017 at 21:38
  • I was making an example. Actually, the raw data is picosecond, and I want to label it as nanosecond. And I would like to manually add some words to the tick makers, e.g. change "1,2,3" to "Atom 1, Atom 2, Atom 3". Commented Dec 16, 2017 at 21:48

2 Answers 2

1

Application to your problem:

from matplotlib.ticker import FuncFormatter
from matplotlib.pyplot import show
import matplotlib.pyplot as plt
import numpy as np

a=np.random.random((1000,1000))

# create scaled formatters / for Y with Atom prefix
formatterY = FuncFormatter(lambda y, pos: 'Atom {0:g}'.format(y*0.01))
formatterX = FuncFormatter(lambda x, pos: '{0:g}'.format(x*0.01))

# apply formatters 
fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatterY)
ax.xaxis.set_major_formatter(formatterX)

plt.imshow(a, cmap='Reds', interpolation='nearest')

# create labels
plt.xlabel('nanometer')
plt.ylabel('measure')
plt.xticks(list(range(0, 1001,100)))

plt.yticks(list(range(0, 1001,100)))

plt.show()

Y with Atoms, X with scalen numbers, both with titles

Sources:

A possible solution is to format the ticklabels according to some function as seen in below example code from the matplotlib page.

from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(4)
money = [1.5e5, 2.5e6, 5.5e6, 2.0e7]


def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x * 1e-6)


formatter = FuncFormatter(millions)

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatter)
plt.bar(x, money)
plt.xticks(x, ('Bill', 'Fred', 'Mary', 'Sue'))
plt.show()

matplotlib.org Example


A similar solution is shown in this answer, where you can set a function to label the axis for you and scale it down:

ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x*scale))
ax.xaxis.set_major_formatter(ticks)

Here, you would need to do /100 instead of *scale

The easier way for yours would probably be:

ticks = plt.xticks()/100
plt.gca().set_xticklabels(ticks.astype(int))

(adapted from https://stackoverflow.com/a/10171851/7505395)

Sign up to request clarification or add additional context in comments.

9 Comments

thanks, I got: AttributeError: module 'matplotlib.pyplot' has no attribute 'get_xticks'
I tried, but the labels are squeezed on the left, not evenly distributed.
Note that there is no difference between pylab and pyplot in the functionality it provides. pylab is a wrapper, which essentially consists of two lines: from numpy import *; from matplotlib.pyplot import *. Since it is not really good style to import several packages into the same namespace, pylab is deprecated. All the solutions in this answer will work simply via import matplotlib.pyplot as plt. (I modified your answer and removed the errors in it.)
@ImportanceOfBeingErnest thanks for the tip, adjusted my code example to the Q.
Thank you, I posted here link
|
1

You would use the extent of the image to bring it into a new coordinate space.

At the moment it ranges in the space between 0 and 999. This means the axis limits are (-0.5, 999.5). You can calculate a new extent from a function, e.g. f = lambda x: x/100. and set the result as new extent of the image.

This would make the image occupy the axis range between (-0.005, 9.995). Now it is straight forward to set the tick(label)s as seen in the question.

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))

im = plt.imshow(a, cmap='Reds', interpolation='nearest')

f = lambda x: x/100.
(llx,ulx),(lly,uly) = plt.xlim(),plt.ylim()
im.set_extent([f(llx),f(ulx),f(lly),f(uly)])


plt.xticks(list(range(0, 10)))
plt.yticks(list(range(0, 10)))

plt.show()

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.