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.
Related
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 !
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'm plotting a simple scatter plot:
It represents my data correctly, however there is many datapoints with coordinates (1.00,1.00) and in the plot, they appear under a single marker (top right corner). I'd like to have a functionality that changes the size of every marker according to the number of points it is representing. Will appreciate any help. Here's my code:
def saveScatter(figureTitle, xFeature, yFeature, xTitle, yTitle):
''' save a scatter plot of xFeatures vs yFeatures '''
fig = plt.figure(figsize=(8, 6), dpi=300)
ax = fig.add_subplot(111)
ax.scatter(dfModuleCPositives[names[xFeature]][:], dfModuleCPositives[names[yFeature]][:], c='r', marker='x', alpha=1, label='Module C Positives')
ax.scatter(dfModuleCNegatives[names[xFeature]][:], dfModuleCNegatives[names[yFeature]][:], c='g', alpha=0.5, label='Module C Negatives')
ax.scatter(dfModuleDPositives[names[xFeature]][:], dfModuleDPositives[names[yFeature]][:], c='k', marker='x', alpha=1, label='Module D Positives')
ax.scatter(dfModuleDNegatives[names[xFeature]][:], dfModuleDNegatives[names[yFeature]][:], c='b', alpha=0.5, label='Module D Negatives')
ax.set_xlabel(xTitle, fontsize=10)
ax.set_ylabel(yTitle, fontsize=10)
ax.set_title(figureTitle)
ax.grid(True)
ax.legend(loc="lower right")
fig.tight_layout()
plt.show()
return ax
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()