I am trying to put a colorbar to my image using matplotlib. The issue comes when I try to force the ticklabels to be written in scientific notation. How can I force the scientific notation (ie, 1x10^0, 2x10^0, ..., 1x10^2, and so on) in the ticks of the color bar?
Example, let's create and plot and image with its color bar:
import matplotlib as plot
import numpy as np
img = np.random.randn(300,300)
myplot = plt.imshow(img)
plt.colorbar(myplot)
plt.show()
When I do this, I get the following image:
However, I would like to see the ticklabels in scientific notation... Is there any one line command to do this? Otherwise, is there any hint out there? Thanks!
You could use colorbar's format parameter:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as ticker
img = np.random.randn(300,300)
myplot = plt.imshow(img)
def fmt(x, pos):
a, b = '{:.2e}'.format(x).split('e')
b = int(b)
return r'${} \times 10^{{{}}}$'.format(a, b)
plt.colorbar(myplot, format=ticker.FuncFormatter(fmt))
plt.show()
You can specify the format of the colorbar ticks as follows:
pl.colorbar(myplot, format='%.0e')
There is a more straightforward (but less customizable) way to get scientific notation in a ColorBar without the %.0e formatting.
Create your ColorBar:
cbar = plt.colorbar()
And call the formatter:
cbar.formatter.set_powerlimits((0, 0))
This will make the ColorBar use scientific notation. See the example figure below to see how the ColorBar will look.
The documentation for this function can be found here.
It seems that cbar.formatter.set_powerlimits((0,0)) alone in Joseph's answer does not render math format like $10^3$ yet.
Using further cbar.formatter.set_useMathText(True) gives something like $10^3$.
import matplotlib.pyplot as plt
import numpy as np
img = np.random.randn(300,300)*10**5
myplot = plt.imshow(img)
cbar = plt.colorbar(myplot)
cbar.formatter.set_powerlimits((0, 0))
# to get 10^3 instead of 1e3
cbar.formatter.set_useMathText(True)
plt.show()
generates
plot.
See the document of set_useMathText() here.
PS: Maybe this suits best for a comment. But I do not have enough reputations.
Related
I'm creating a Matplotlib figure, which I need to be quite wide (174 mm) and in .eps format. I also need it to be created with LaTeX for consistency with other figures. The problem is that the rightmost parts of the axes do not appear in the output figure, and the legend's box and handles also disappear.
The problem appears only if the figure if very wide, when I use LaTeX to produce it, and when I save it in .eps. The figure is as expected if it is thinner, if I save it in .pdf or .png, or if I just replace plt.savefig(...) with plt.show() and use Matplotlib's default viewer.
To be clearer, consider the following code.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 100)
y = np.exp(x)
mpl.rcParams['text.usetex'] = True
mm = 1/25.4
fig = plt.figure(figsize=(174*mm, 44*mm))
plt.plot(x, y, label='exponential')
plt.legend(loc='lower right')
plt.tight_layout()
plt.savefig('test.eps')
This outputs the following figure, where the legend handle and the rightmost part of the axes do not appear.
If it can help, the .eps file output by the above code is available here.
I have been trying to plot some panels using ImageGrid. When I use grid.cbar_axes[0].colorbar(im) to set the colorbar the colors look fine, but the scale on the colorbar reads like it's going from 2x10^0 to None.
I have tried dozens of workarounds but nothing worked. Here's the figure I'm trying to make (my wrong version):
Unfortunately I couldn't make a MWE that perfectly reproduces the problem. I did produce a MWE that partially reproduces it. If I use this code:
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
from matplotlib.colors import LogNorm
def get_demo_image():
import numpy as np
from matplotlib.cbook import get_sample_data
f = get_sample_data("axes_grid/bivariate_normal.npy", asfileobj=False)
z = np.load(f)
return abs(z), (-3, 4, -4, 3)
F = plt.figure(figsize=(5.5, 3.5))
grid = ImageGrid(F, 111, # similar to subplot(111)
nrows_ncols=(1, 3),
axes_pad=0.1,
add_all=True,
label_mode="L",
cbar_mode='single'
)
Z, extent = get_demo_image() # demo image
im1 = Z
im2 = Z
im3 = Z
vmin, vmax = 1e-3, 1e10
for i, im in enumerate([im1, im2, im3]):
ax = grid[i]
imc = ax.pcolormesh(range(15), range(15), im, norm=LogNorm(vmin=vmin, vmax=vmax), linewidth=0, rasterized=True)
cb=grid.cbar_axes[0].colorbar(imc)
I get almost the same behavior, except that the upper limit appears to be fine. The lower limit still presents the same weird behavior, no matter what values I use for vmin and vmax.
Any idea of what might be going on?
Although the official example uses something similar to
cb=grid.cbar_axes[0].colorbar(imc), which would translate here into grid[2].cax.colorbar(im), I'm lost on why that would even make sense.
Instead, the usual way to produce a colorbar would also work here, using the colorbar method of Figure with the ScalarMappable (here imc) as argument
and the axes to produce the colorbar as keywordargument to cax (here grid[2].cax):
cb=F.colorbar(imc, cax=grid[2].cax)
Consider the following python module 'plot_figure.py' defining PlotFigure(). Note that it is a pseudo-code.
import matplotlib.pyplot as plt
def PlotFigure(x)
# Some other routines..
plt.plot(x)
# Some other routines..
I would like to call plot_figure.PlotFigure, but after plotting a figure, I would like to change the line widths of this figure. Even though PlotFigure() may include other routines, the lines in the figure are plotted using plt.plot() as shown in the above pseudo-code.
The following is the code that calls plot_figure.PlotFigure()
#!/usr/bin/python
import matplotlib.pyplot as plt
import plot_figure
x_data = [ # some data ]
plot_figure.PlotFigure(x_data)
#***I would like to change the line width of the figure here***
plt.show()
I know that I can get the figure handle using fig = plt.gcf(), but plt.setp(fig, linewidth=2) doesn't work.
Could anyone give some suggestion on this?
First let me note that the generic way to set the linewidth (or any other plot parameter) would be to give it as an argument to the plot command.
import matplotlib.pyplot as plt
def PlotFigure(x, **kwargs):
# Some other routines..
plt.plot(x, linewidth=kwargs.get("linewidth", 1.5) )
# Some other routines..
and the call
plot_figure.PlotFigure(x_data, linewidth=3.)
If this really is not an option, you'd need to get the lines from the figure.
The easiest case would be if there was only one axes.
for line in plt.gca().lines:
line.set_linewidth(3.)
I have data that is in the range -70,0 that I display using imshow() and would like to use a non-linear colorbar to represent the data as I have paterns both in the -70,-60 range and -70,0 range.
I would like the easiest way to rescale/renormalize using an arbitrary function (see example) the colorbar so that all paterns appear nicely.
Here is an example of data and function:
sample_data=(np.ones((20,20))*np.linspace(0,1,20)**3)*70-70
def renorm(value):
"""
Example of the way I would like to adjust the colorbar but it might as well be an arbitrary function
Returns a number between 0 and 1 that would correspond to the color wanted on the original colorbar
For the cmap 'inferno' 0 would be the dark purple, 0.5 the purplish orange and 1 the light yellow
"""
return np.log(value+70+1)/np.log(70+1)
This is what I managed to do:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import PowerNorm
sample_data=(np.ones((20,20))*np.linspace(0,1,20)**3)*70-70
plt.figure()
im = plt.imshow(sample_data+70, norm=PowerNorm(gamma=0.5))
cbar = plt.colorbar(orientation='horizontal')
cbar.ax.set_xticklabels(np.arange(-70, 0, 8))
plt.show()
You can change the gamma.
However, this kind of visualization is not recommended, see: http://matplotlib.org/users/colormapnorms.html
under "Power-law" -> "Note"
In matplotlib, the axes are sometimes displayed in standard form. The numbers are shown by the ticks and something like '1e-7' appears by the axis. Is there a way to change that to a written out $\times 10^{-7}$?
I am not looking to change the labels on each individual tick. I am looking to change the text that appears once at the bottom of the axis saying '1e-7'.
The simplest answer: Use the latex mode:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['text.usetex'] = True
x = np.arange(10000, 10011)
plt.plot(x)
plt.show()
Result:
EDIT:
Actually you don't need to use latex at all. The ScalarFormatter which is used by default has an option to use scientific notation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
x = np.arange(10000, 10011)
fig, ax = plt.subplots(1)
ax.plot(x)
formatter = mticker.ScalarFormatter(useMathText=True)
ax.yaxis.set_major_formatter(formatter)
plt.show()
Result:
Have a look at matplotlib.ticker. It allows you control of the formatting of ticks including the labels.