I would like to do subplots of tricontourf. I tried this but it does not work, I obtain the error message: RuntimeError: No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf).
fig, (ax1, ax2, ax3) = plt.subplots(1, 3)
fig = plt.figure()
# background_field
levels=np.linspace(0,max(max_ls, lc),5)
levels=np.r_[levels,[lc_smooth_min]]
levels=np.sort(levels)
print(levels)
ax1.tricontourf(X, Y, background_field(X,Y,Z), levels, cmap ='inferno')
plt.colorbar(boundaries=levels)
plt.xlim([0, 3])
plt.ylim([0, 0.5])
plt.xlabel("X")
plt.ylabel("Y")
# echelle_kolmogorov
ax2.tricontourf(X, Y, echelle_1(X,Y,Z), levels, cmap ='inferno')
plt.colorbar(boundaries=levels)
plt.xlim([0, 3])
plt.ylim([0, 0.5])
plt.xlabel("X")
plt.ylabel("Y")
# echelle_HTLES
ax3.tricontourf(X, Y, echelle_2(X,Y,Z), levels, cmap ='inferno')
plt.colorbar(boundaries=levels)
plt.xlim([0, 3])
plt.ylim([0, 0.5])
plt.xlabel("X")
plt.ylabel("Y")
plt.show()
Is it possible to perform subplots of tricontourf without using imshow?
Can someone explain me how should I do it?
Thanks a lot !
Related
I am working with the matplotlib library to generate colored graphs which need to have specific points overlayed on top of them. After messing around with matplotlib, I came up with a method to properly color my grid, however I am unable to plot points manually.
def generate_grid(x, y, data):
fig, ax = plt.subplots(1, 1, tight_layout=True)
my_cmap = matplotlib.colors.ListedColormap(['grey'])
my_cmap.set_bad(color='w', alpha=0)
for x in range(x + 1):
ax.axhline(x, lw=2, color='k', zorder=5)
for y in range(y+1):
ax.axvline(y, lw=2, color='k', zorder=5)
ax.imshow(data, interpolation='none', cmap=my_cmap,
extent=[0, y, 0, x], zorder=0)
plt.locator_params(axis="x", nbins=x+1)
plt.locator_params(axis="y", nbins=y+1)
locs, labels = plt.xticks()
labels = [int(item)+1 for item in locs]
plt.xticks(locs, labels)
locs, labels = plt.yticks()
z = len(locs)
labels = [z-int(item) for item in locs]
plt.yticks(locs, labels)
ax.xaxis.tick_top()
plt.show()
How would I go about plotting a point at any given location ie at (4,2) or (2,1)?
You may simply use the scatter method from within your generate_grid function, for instance, immediately before plt.show().
However, note that if you simply use ax.scatter(2,1, s=50) the symbol will end up under your grid.
You need to play with the zorder parameter to ensure that it appears over the grid. For instance ax.scatter(2,1, s=50, zorder=50) did the trick for me:
I create two scatterplots with matplotlib in python with this code, the data for the code is here:
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
fig = plt.figure(figsize=(20,12))
ax1 = fig.add_subplot(111)
ax3 = ax1.twinx()
norm = Normalize(vmin=0.95*min(arr), vmax=1.05*max(arr))
ax1.scatter(x, y1, s=20, c=arr, cmap='Blues_r', norm=norm, marker='x', label='bla1')
ax3.scatter(x, y2, s=(20*(1.1-arr))**3.5, c=arr, cmap='Reds_r', norm=norm, marker='^', label='bla1')
The created fig. looks like this:
So, the dot size (in ax3) and the dot colour (in ax1 and ax3) are taken from arrays containing floats with all kinds of values in the range [0,1]. My question: How do I create a legend that displays the corresponding y-values for, let's say 5 different dot sizes and 5 different colour nuances?
I would like the legend to look like in the figure below (source here), but with the colour bar and size bar put into a single legend, if possible. Thanks for suggestions and code!
# using your data in dataframe df
# create s2
df['s2'] = (20*(1.1-df.arr))**3.5
fig = plt.figure(figsize=(20,12))
ax1 = fig.add_subplot(111)
ax3 = ax1.twinx()
norm = Normalize(vmin=0.95*min(df.arr), vmax=1.05*max(df.arr))
p1 = ax1.scatter(df.x, df.y1, s=20, c=df.arr, cmap='Blues_r', norm=norm, marker='x')
fig.colorbar(p1, label='arr')
p2 = ax3.scatter(df.x, df.y2, s=df.s2, c=df.arr, cmap='Reds_r', norm=norm, marker='^')
fig.colorbar(p2, label='arr')
# create the size legend for red
for x in [15, 80, 150]:
plt.scatter([], [], c='r', alpha=1, s=x, label=str(x), marker='^')
plt.legend(loc='upper center', bbox_to_anchor=(1.23, 1), ncol=1, fancybox=True, shadow=True, title='s2')
plt.show()
There's no legend for p1 because the size is static.
I think this would be better as two separate plots
I used Customizing Plot Legends: Legend for Size of Points
Separate
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(20, 10))
norm = Normalize(vmin=0.95*min(df.arr), vmax=1.05*max(df.arr))
p1 = ax1.scatter(df.x, df.y1, s=20, c=df.arr, cmap='Blues_r', norm=norm, marker='x')
fig.colorbar(p1, ax=ax1, label='arr')
p2 = ax2.scatter(df.x, df.y2, s=df.s2, c=df.arr, cmap='Reds_r', norm=norm, marker='^')
fig.colorbar(p2, ax=ax2, label='arr')
# create the size legend for red
for x in [15, 80, 150]:
plt.scatter([], [], c='r', alpha=1, s=x, label=str(x), marker='^')
plt.legend(loc='upper center', bbox_to_anchor=(1.2, 1), ncol=1, fancybox=True, shadow=True, title='s2')
plt.show()
I want to plot some data I have (square wave signals) in a subplot but I want to remove the axis for better visualization. This results in not having a ylabel. I thought I could add a simple text() so I could manually insert the text I want, but I can't seem to be able to use negative values for the y axis (as I could without a subplot). The code I thought would work was:
fig, (ax1, ax2, ax3, ax4, ax5, ax6)= plt.subplots(6,1)
#plot
ax1.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.clk_y, linewidth=2, color='black')
ax2.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.clkbar_y, linewidth=2, color='black')
ax3.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.q1_y, linewidth=2, color='C0')
ax4.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.q2_y, linewidth=2, color='C1')
ax5.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.q1bar_y, linewidth=2, color='C2')
ax6.plot(PathClockGeneration_4.q2bar_x,PathClockGeneration_4.q2bar_y, linewidth=2, color='C3')
#axis
ax1.axis('off')
ax2.axis('off')
ax3.axis('off')
ax4.axis('off')
ax5.axis('off')
ax6.axis('off')
#text
ax1.text(-1.5, 2, 'MyText')
If i try the last line as ax1.text(0, 2, 'MyText') it works fine, but the placement of the text is not the one I want. I suppose this comes from the size my plot is allowed to have and I would need to change it, how to do so?
EDIT
This is what I obtain hiding the axis manually (which can allow me to insert a ylabel). This is what I really want as plot obtained from the coded posted above by commenting ax1.text(-1.5, 2, 'MyText')
You can use fig instead of the ax1 to place your text. The arguments 0.05, 0.6 are the x and y coordinates in relative scale. You can choose them as per your taste.
Complete answer
import numpy as np
import matplotlib.pyplot as plt
fig, (ax1, ax2, ax3, ax4, ax5, ax6) = plt.subplots(6,1)
x = np.linspace(0, 4*np.pi, 100)
y = np.sin(x)
ax1.plot(x, y, linewidth=2, color='black')
ax2.plot(x, y, linewidth=2, color='black')
ax3.plot(x, y, linewidth=2, color='C0')
ax4.plot(x, y, linewidth=2, color='C1')
ax5.plot(x, y, linewidth=2, color='C2')
ax6.plot(x, y, linewidth=2, color='C3')
# Hiding axis
for ax in [ax1, ax2, ax3, ax4, ax5, ax6]:
ax.axis('off')
fig.text(0.05, 0.6, 'MyText', rotation=90, fontsize=20)
plt.show()
I have a color coded plot. Here is a part of the code:
fig = plt.figure(figsize=(10,10))
color_scheme = plt.get_cmap('cool')
gs = gridspec.GridSpec(1, 1)
ax1 = plt.subplot(gs[0])
gs.update(left=0.15,bottom=0.15,right=0.80,top=0.95)
cax = fig.add_axes([0.80, 0.15, 0.03, 0.80])
im = ax1.scatter(x, y, c=z, edgecolors='black', marker='.', s=40, lw=1, cmap=color_scheme, vmin=0, vmax=10)
cb = fig.colorbar(im, cax=cax)
for t in cb.ax.get_yticklabels(): t.set_fontsize(12)
The problem is that I want to connect the dots with a line, and it doesn't work to use marker='-' and it also doesn't work if I use ax1.plt. How can I do this?
What I actually need is to fit a line to some points and color it the same color as the points (the points I fit to will all have same color)
Instead of using
ax1.scatter(x, y, ...)
use
ax1.plot(x, y, 'o-', ...) # three dots meaning you can configure markers, linestyle, etc.
This works bacause of 'o-' argument, which is a line plot with markers at every data point.
Plot the same x and y-data separately with a standard ax.plot behind your scatter plot.
ax1.plot(x, y, '-')
im = ax1.scatter(x, y, c=z, edgecolors='black', marker='.', s=40, lw=1, cmap=color_scheme, vmin=0, vmax=10)
This should give you your cmapped scatter plot with the lines behind the scatter-points.
It's possible to set all labels at once in Matplolib?
For example, I have this piece of code to plot a scatter plot:
cmap = plt.get_cmap('Set1')
colors = [cmap(i) for i in numpy.linspace(0, 1, simulations+1)]
plt.figure(figsize=(7, 7))
plt.scatter(coords[:, 0], coords[:, 1], marker='o', c=colors, s=50, edgecolor='None')
plt.legend(loc='lower left',)
where simulations = 7 and coords is a numpy.array with shape (7, 2).
This gives me a plot like that:
If I change the last line for:
plt.scatter(coords[:, 0], coords[:, 1], marker='o', c=colors, s=50, edgecolor='None', label=range(simulations))
plt.legend(loc='lower left')
I get:
I'm wondering if I'll have to do a loop to do the scatter and set each label of if there is some way to do all at once.
Thank you.
I'm not sure how to do it with a scatter plot. But I'm not sure if there is an advantage to use scatter rather than plot if you want different labels.
How about this?
import numpy as np
import matplotlib.pyplot as plt
n = 10
coords = np.random.random((n,2))
cmap = plt.get_cmap('Set1')
for i, (x, y) in enumerate(coords):
plt.plot(x, y, 'o', color=cmap(i/float(n)), label='%i'%i, ms=9, mec='none')
plt.axis((-0.5, 1.5, -0.5, 1.5))
plt.legend(loc='lower left', numpoints=1, frameon=False)
plt.show()