Using matplotlib, how do I whiten the background of the axis label? - python

Is there a way to whiten out the background of the axis label so that when it crosses the axis line itself, the latter does not run through it?
For example, this script (the best I managed so far)
#!/usr/bin/python
import matplotlib.pyplot as plt
xx=[1,2,3]
yy=[2,3,4]
dy=[0.1,0.2,0.05]
fig=plt.figure()
ax=fig.add_subplot(111)
ax.errorbar(xx,yy,dy,fmt='ro-',ms=6,elinewidth=4)
ax.set_xlim([0.,3.4])
ax.set_ylim([0.,4.4])
ax.set_xlabel(r'$T/t$',fontsize=16)
ax.set_ylabel(r'$S(\mathbf{Q})L^{1+\eta}$',fontsize=16)
# position the axis labels
ax.xaxis.set_label_coords(1,0)
ax.yaxis.set_label_coords(0.1,0.93)
ax.yaxis.get_label().set_rotation('horizontal')
ax.yaxis.get_label().set_backgroundcolor('w')
#ax.yaxis.get_label().set_zorder(222) #doesn't do the trick
plt.show()
produces almost what I'm looking for, but still the y-axis runs over the label: .

By default, the left spine has a zorder of 2.5. For some reason this seems to cause problems; maybe there's something in the code which only works if they're integral? Anyway, if you add
ax.spines['left'].set_zorder(2)
or more generally
ax.spines['left'].set_zorder(ax.yaxis.get_label().get_zorder()-1)
before the show, it should work. Also, set_ylabel returns the ylab object itself, so if you use "ylab = ax.set_ylabel(stuff)" you can avoid all the ax.yaxis.get_label() calls later.

Does this link help you?
http://matplotlib.sourceforge.net/faq/howto_faq.html#automatically-make-room-for-tick-labels
You can simply shift the y-axis to the right to allows some space for the $S(\mathbf{Q})L^{1+\eta}$ mark be fully placed before the axis line.

Related

How to set gridlines behind boxplots in seaborn/matplotlib? [duplicate]

In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.

How does matplotlib 1.5.3's tight_layout() interact with subplots_adjust()?

I am using Matplotlib 1.5.3 in Python 3. I have a 3x3 subplot structure, or more generically an unspecified subplot structure that I'm trying to add a color bar to. As per this thread, an apparently good way to do this is to distort the subplots with subplots_adjust(), and add the colorbar as a new axes. Except, I have tight_layout() enabled, and that totally messes with things. Here is the function that, based on what I have read about subplots_adjust(), should work:
import matplotlib.pyplot as plt
def add_colorbar(last_im):
SPACE = 0.2 # portion of final width reserved for colorbar and its padding
PADDING = 0.5 # portion of reserved space reserved for padding
fig = plt.gcf()
# expand image to make room for colorbar
w,h = fig.get_size_inches()
fig.set_size_inches((w/(1-SPACE), h))
# shrink right side of subplot to create empty space on
# right hand side
fig.subplots_adjust(right=0.9*(1-SPACE)) # 0.9 being the original value
# create colorbar axes, place in empty space with padding
cbax = fig.add_axes([1-SPACE*(1-PADDING/2), 0.15,
SPACE*(1-PADDING), 0.7])
fig.colorbar(last_im, cax=cbax)
But the subplot configuration is kept centered, so this creates basically no space, and the color bar is drawn straight over the subplots. I have also tried using plt.tight_layout(rect=[0, 0, 1-SPACE, 1]) instead of subplots_adjust(), but this seems to do even less than the subplots_adjust() statement, and messes with basically just the sizes of the individual subplots. It seems neither of these functions work as advertised for me. What am I missing? Faulty plot shown below, with plot titles censored to be on the safe side.
Alternatively, I'd be fine with a solution for adding a colorbar that will generically work for a figure with any subplot configuration, but I'd prefer to understand the baffling behavior of subplots_adjust() and the tight_layout() rect.
EDIT: Problem ended up being that I made tight_layout() calls erroneously after running add_colorbar(). Correct behavior is observed now that I have removed the calls.

PyPlot coordinate reader ruined when changing axis labels

Generally when plotting with pyplot we have the current (x,y) values at the bottom right:
But, what happens if you relabel? Code:
import matplotlib.pyplot as plt
plt.ion()
plt.draw()
plt.plot([(i,i) for i in range(10)])
plt.gca().set_xticklabels((1,2,3,4,5,6,7,8,9,10))
plt.draw()
You get:
As you see the x value is ruined, that is, is no longer displayed. This may make sense for non- numeric labeling, and may be difficult to handle, but this actually happened to me while working with a twin axis, which I need to be a transformation of the first. If I relabel the twin the coordinates do not appear as well, even though the main axis is untouched. Is there a way to retrieve coordinate display capability?. If someone feels a code to produce and alter a twin axis is necessary let me know.
When set_xticklabels is used, it will overwrite the formatter used. So it has to be set again:
plt.gca().xaxis.set_major_formatter(FormatStrFormatter('%.5f'))
If you want to display the values transformed somehow, then you have to use FuncFormatter, which accepts a function of tick and position, and returns the label. Read about it here. To combine it with nice scalar formatting (in the link as well) you can use something like:
plt.gca().xaxis.set_major_formatter(FuncFormatter(
lambda t,p,f=yourfunc: ScalarFormatter().format_data_short(f(t))))
You probably want to initialize the ScalarFormatter outside.

setting tickslabel in matplotlib disables mouse cursor position

Whenever I plot something in matplotlib, moving the mouse over the plot shows at the bottom the x and y position of the cursor. This is very convenient when exploring data.
Now, If I set the ticklabels to something else, the x position of the cursor at the bottom of the plot is empty, while the gui keeps track of the y position. Is there a way to keep getting the x position?
This is a simple example of this happening:
import numpy as np
fig, ax = plt.subplots()
x=np.linspace(0,np.pi)
y=np.sin(x)
ax.plot(x,y)
ax.set_xticks([0,np.pi/2,np.pi])
ax.set_xticklabels(['0','pi/2','pi'])
plt.show()
No, there is no easy way to do this.
When you set the labels with a list of strings you set the xaxis.major_formatter to be FixedFormatter (doc) which has some peculiar behavior to make it work (it always returns '', unless you give it a third argument which given when it labels the x-axis, but not otherwise). The marking of where the cursor is is generated using the major_formatter and when you call a FixedFormatter it returns '', which is what is displayed.
If you really want this, you have to write your own call back, see Color values in imshow for matplotlib? for a starting point. (or subclass axes and re-implement format_coord (around line 2903 in axes.py in current matplotlib master branch)

Matplotlib: draw grid lines behind other graph elements

In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.

Categories

Resources