matplotlib rc colorcycle argument with scatterplot - python

i have configured my own colorcycle in my rc-file (axes.color_cycle) which works fine for the plot command but not for something like:
for i in range(len(x)):
ax.scatter(x[i],y[i],s=area[i], alpha = 0.5)
any ideas how to fix that ?

You dont need to loop in order to use .scatter. You can prepare a list of colors and provide it with color= to scatter. The color method is implemented in such a way that the list of colors does not need to match the length of the data, it gets automatically repeated/cycled or truncated if necessary.
So for example:
fig, ax = plt.subplots()
n = 50
x = np.random.randint(0,100,n)
y = np.random.randint(0,100,n)
area = np.random.randint(20,100,n)
ax.scatter(x, y, s=area, alpha=0.5, color=mpl.rcParams['axes.color_cycle'])
Results in:

Related

Matplotlib Draw a Constant y Axis

I want to use matpoltlib to make a plot that with a constant y axis(always from 0 to 14 and the gap is 1), since I want to make labels for them and my dot values will be(x, y) where y is from 0 to 14 gap 1, and a changing x axis. I already tried to play with y ticks. And here is my code for that:
fig, ax = plt.subplots()
fig.canvas.draw()
plt.yticks(np.arange(0, 14, 1))
labels = [item.get_text() for item in ax.get_yticklabels()]
labels[1] = 'Not Detected'
labels[2] = 'A/G'
labels[3] = 'G/G'
labels[4] = 'C/T'
labels[5] = 'C/C'
labels[6] = 'A/A'
labels[7] = '-1'
labels[8] = 'ε3/ε3'
labels[9] = 'A/C'
labels[10] = 'T/T'
labels[11] = 'C/G'
labels[12] = 'ε2/ε3'
labels[13] = 'G/T'
ax.set_yticklabels(labels)
what I'm thinking about is to use some values or lines with white color so those y axis will appear. But I'm looking for a more efficient way of doing it. And here is the diagram I generated with the current code. It only shows C/C right now and I want all labels to appear in the diagram.
I tried draw white points with:
x1 = np.arange(n)
y1 = np.arange(1,15,1)
plt.scatter(x1,y1,color = 'white')
Which did give me what I want: But I was wondering whether there is a lib setting that can do this.
I would recommend just using a fixed locator and fixed formatter for your y axis. The function, ax.set_yticklabels() is simply a convenience wrapper for these tick methods.
I would also recommend having your y_labels in a list or using a loop structure as this is a more generalizable and modifiable implementation.
If I'm understanding the goals of your plot correctly, something like this may work well for you.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
#make some data
x = np.arange(25)
y = np.random.randint(1, 14, size=25)
#convert y labels to a list
y_labels = [
'Not Detected','A/G','G/G','C/T','C/C','A/A',
'-1','ε3/ε3', 'A/C','T/T','C/G','ε2/ε3','G/T'
]
#define figure/ax and set figsize
fig, ax = plt.subplots(figsize=(12,8))
#plot data, s is marker size, it's points squared
ax.scatter(x, y, marker='x', s=10**2, color='#5d2287', linewidth=2)
#set major locator and formatter to fixed, add grid, hide top/right spines
locator = ax.yaxis.set_major_locator(mpl.ticker.FixedLocator(np.arange(1, 14)))
formatter = ax.yaxis.set_major_formatter(mpl.ticker.FixedFormatter(y_labels))
grid = ax.grid(axis='y', dashes=(8,3), alpha=0.3, color='gray')
spines = [ax.spines[x].set_visible(False) for x in ['top','right']]
params = ax.tick_params(labelsize=12) #increase label font size

Defining a function to make automated plots using matplotlib

I am new to python and I need to do a class made of different functions. Each function should be plotting different type of plot with predefined color, size, etc. The user should only call the function and enter two values (x=df or lst, y=df or lst and z the title of the plot) and then get the plot with the format that I have already predefined in the code.
Here is my code:
class Plotter:
def plot_signal(x,y):
plt.figure(figsize=(20, 5) )
plt.plot(x,
y,
color=(142/255.0,186/255.0,229/255.0), alpha=0.1 , linewidth=0.5 );
plt.xlim(left=0)
plt.xlabel('Time [s]', fontsize=11, fontname='Arial')
plt.ylabel('Force [kN]', fontsize=11, fontname='Arial')
plt.xticks(fontsize=8)
plt.yticks(fontsize=8)
plt.savefig(r"filepath\\filename.jpg")
plt.show()
plt.title(z)
return plt.show()
z = "trial"
x = np.random.rand(100)*10
y = np.random.rand(100)
plot_signal(x,y)
and the result (as seen in the photo), is a plot with a different color other than the color I chose, no title, and not even the figure size, it does also save my file, and I do not know how to fix it or what is the problem.
enter image description here
def plot_signal(x, y, z):
plt.figure(figsize=(20, 5))
plt.plot(x, y, color=(142/255.0,186/255.0,229/255.0))
plt.xlabel('Time [s]', fontsize=11, fontname='Arial')
plt.ylabel('Force [kN]', fontsize=11, fontname='Arial')
plt.xticks(fontsize=8)
plt.title(z)
plt.yticks(fontsize=8)
plt.show()
you can change the color by just using color string, the list of the color string can be seen here
example
plt.plot(x, y, color='red')
based on your code, you use alpha=0.1 which means the color will be transparent if it close to 0.
plt.savefig(r"filepath\\filename.jpg")
this line will save your file, you can remove it

Python : How to create a 2D density map/heat map

I'm coding with python.
I have 3 arrays x, y and z, and I would like to do 2d density map of the z values in the plan (x,y) with colorbar.
So in my plot, the color at the point x[0] and y[0] would be determined by the value of z[0], the color at the point x[1] and y[1] would be determined by the value of z[1], etc.
Does anyone know how to do this ?
Thank you
Check out https://matplotlib.org/api/_as_gen/matplotlib.pyplot.scatter.html
For different colormaps: https://matplotlib.org/tutorials/colors/colormaps.html
A sample piece of code for your need will be something like this
#--------------------------Plotting starts here---------------------------------#
fig, ax0 = plt.subplots()
im0 = plt.scatter(x,y,s=1,c=z, cmap='bwr')
#------------------if you want to use pcolormesh-------------------
#----------and have Z values stored as a numpy array Data---------------------#
#X,Y = np.meshgrid(x,y)
#im0 = ax0.pcolormesh(X,Y,Data, cmap="YourFavouriteColormap')
cbar = fig.colorbar(im0,ax=ax0)
ax0.set_title("Your title")
plt.xlabel("xlabel")
plt.ylabel("ylabel")
filename = "prefix" + "."+ "fileformat"
plt.savefig(filename)
Edit 1:
From one of your comments, if you have grid data, you can try pcolormesh and try shading, an optional argument for interpolation.
shading{'flat', 'gouraud'}, optional
The fill style, Possible values:
'flat': A solid color is used for each quad. The color of the quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by C[i, j].
'gouraud': Each quad will be Gouraud shaded: The color of the corners (i', j') are given by C[i',j']. The color values of the area in between is interpolated from the corner values. When Gouraud shading is used, edgecolors is ignored.
You can use matplotlib's scatter plots with legends and grid where the size of each circle can be referred to z values. This is an example I got from here:
volume = np.random.rayleigh(27, size=40)
amount = np.random.poisson(10, size=40)
ranking = np.random.normal(size=40)
price = np.random.uniform(1, 10, size=40)
fig, ax = plt.subplots()
scatter = ax.scatter(volume, amount, c=ranking, s=0.3*(price*3)**2,
vmin=-3, vmax=3, cmap="Spectral")
legend1 = ax.legend(*scatter.legend_elements(num=5),
loc="upper left", title="Ranking")
ax.add_artist(legend1)
kw = dict(prop="sizes", num=5, color=scatter.cmap(0.7), fmt="$ {x:.2f}",
func=lambda s: np.sqrt(s/.3)/3)
legend2 = ax.legend(*scatter.legend_elements(**kw),
loc="lower right", title="Price")
plt.show()
Output:
In response to your comment AshlinJP :
Either way I still got the error message : "imshow() got multiple values for keyword argument 'cmap'"
I don't know if it has any importance but I use python 2.7
Actually my code is :
import numpy as np
import matplotlib.pyplot as plt
x,y,z = np.loadtxt('gamma.txt', unpack = True)
fig, ax0 = plt.subplots()
cmap = plt.get_cmap('viridis')
im0 = ax0.imshow(x,y,z, cmap=cmap, interpolation="gaussian")
cbar = fig.colorbar(im0,ax=ax0)
ax0.set_title("Your title")
plt.xlabel("xlabel")
plt.ylabel("ylabel")

Manually set color of points in legend

I'm making a scatter plot which looks like this:
(MWE at bottom of question)
As can be seen in the image above the colors of the points in the legend are set to blue automatically by matplotlib. I need to set this points to some other color not present in the colormap (ie: black) so they won't generate confusion with the colors associated with said colormap.
I looked around but the matplotlib.legend module does not seem to accept a color keyword. Is there any way to do this?
Here's the MWE:
import matplotlib.pyplot as plt
import numpy as np
def rand_data():
return np.random.uniform(low=0., high=1., size=(100,))
# Generate data.
x, y, x2, x3 = [rand_data() for i in range(4)]
# This data defines the markes and labels used.
x1 = np.random.random_integers(7, 9, size=(100,))
# Order all lists so smaller points are on top.
order = np.argsort(-np.array(x2))
# Order x and y.
x_o, y_o = np.take(x, order), np.take(y, order)
# Order list related to markers and labels.
z1 = np.take(x1, order)
# Order list related to sizes.
z2 = np.take(x2, order)
# Order list related to colors.
z3 = np.take(x3, order)
plt.figure()
cm = plt.cm.get_cmap('RdYlBu')
# Scatter plot where each value in z1 has a different marker and label
# assigned.
mrk = {7: ('o', '7'), 8: ('s', '8'), 9: ('D', '9')}
for key, value in mrk.items():
s1 = (z1 == key)
plt.scatter(x_o[s1], y_o[s1], marker=value[0], label=value[1],
s=z2[s1] * 100., c=z3[s1], cmap=cm, lw=0.2)
# Plot colorbar
plt.colorbar()
# Plot legend.
plt.legend(loc="lower left", markerscale=0.7, scatterpoints=1, fontsize=10)
plt.show()
You can obtain the legend handles and change their colors individually:
ax = plt.gca()
leg = ax.get_legend()
leg.legendHandles[0].set_color('red')
leg.legendHandles[1].set_color('yellow')
Adding to the other answers – I've had trouble in the past changing color of legend markers with set_color. An alternate approach is to build the legend yourself:
import matplotlib.lines as mlines
eight = mlines.Line2D([], [], color='blue', marker='s', ls='', label='8')
nine = mlines.Line2D([], [], color='blue', marker='D', ls='', label='9')
# etc etc
plt.legend(handles=[eight, nine])
Building legends from scratch can sometimes save the hassle of dealing with the obscure internals of an already built legend. More information in Matplotlib docs here.
You can retrieve the label of each legend handle with lh.get_label() if you want to map colors to specific labels.
For my purposes it worked best to create a dict from legendHandles and change the colors like so:
ax = plt.gca()
leg = ax.get_legend()
hl_dict = {handle.get_label(): handle for handle in leg.legendHandles}
hl_dict['9'].set_color('red')
hl_dict['8'].set_color('yellow')
While I found that the solution with legendHandles[i].set_color did not work for errorbar, I managed to do the following workaround:
ax_legend = fig.add_subplot(g[3, 0])
ax_legend.axis('off')
handles_markers = []
markers_labels = []
for marker_name, marker_style in markers_style.items():
pts = plt.scatter([0], [0], marker=marker_style, c='black', label=marker_name)
handles_markers.append(pts)
markers_labels.append(marker_name)
pts.remove()
ax_legend.legend(handles_markers, markers_labels, loc='center', ncol=len(markers_labels), handlelength=1.5, handletextpad=.1)
See this GitHub issue as well.

Laying out several plots in matplotlib + numpy

I am pretty new to python and want to plot a dataset using a histogram and a heatmap below. However, I am a bit confused about
How to put a title above both plots and
How to insert some text into bots plots
How to reference the upper and the lower plot
For my first task I used the title instruction, which inserted a caption in between both plots instead of putting it above both plots
For my second task I used the figtext instruction. However, I could not see the text anywhere in the plot. I played a bit with the x, y and fontsize parameters without any success.
Here is my code:
def drawHeatmap(xDim, yDim, plot, threshold, verbose):
global heatmapList
stableCells = 0
print("\n[I] - Plotting Heatmaps ...")
for currentHeatmap in heatmapList:
if -1 in heatmapList[currentHeatmap]:
continue
print("[I] - Plotting heatmap for PUF instance", currentHeatmap,"(",len(heatmapList[currentHeatmap])," values)")
# Convert data to ndarray
#floatMap = list(map(float, currentHeatmap[1]))
myArray = np.array(heatmapList[currentHeatmap]).reshape(xDim,yDim)
# Setup two plots per page
fig, ax = plt.subplots(2)
# Histogram
weights = np.ones_like(heatmapList[currentHeatmap]) / len(heatmapList[currentHeatmap])
hist, bins = np.histogram(heatmapList[currentHeatmap], bins=50, weights=weights)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
ax[0].bar(center, hist, align='center', width=width)
stableCells = calcPercentageStable(threshold, verbose)
plt.figtext(100,100,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", fontsize=40)
heatmap = ax[1].pcolor(myArray, cmap=plt.cm.Blues, alpha=0.8, vmin=0, vmax=1)
cbar = fig.colorbar(heatmap, shrink=0.8, aspect=10, fraction=.1,pad=.01)
#cbar.ax.tick_params(labelsize=40)
for y in range(myArray.shape[0]):
for x in range(myArray.shape[1]):
plt.text(x + 0.5, y + 0.5, '%.2f' % myArray[y, x],
horizontalalignment='center',
verticalalignment='center',
fontsize=(xDim/yDim)*5
)
#fig = plt.figure()
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(60.5,55.5)
plt.savefig(dataDirectory+"/"+currentHeatmap+".pdf", dpi=800, papertype="a3", format="pdf")
#plt.title("Heatmap for PUF instance "+str(currentHeatmap[0][0])+" ("+str(numberOfMeasurements)+" measurements; "+str(sizeOfMeasurements)+" bytes)")
if plot:
plt.show()
print("\t[I] - Done ...")
And here is my current output:
Perhaps this example will make things easier to understand. Things to note are:
Use fig.suptitle to add a title to the top of a figure.
Use ax[i].text(x, y, str) to add text to an Axes object
Each Axes object, ax[i] in your case, holds all the information about a single plot. Use them instead of calling plt, which only really works well with one subplot per figure or to modify all subplots at once. For example, instead of calling plt.figtext, call ax[0].text to add text to the top plot.
Try following the example code below, or at least read through it to get a better idea how to use your ax list.
import numpy as np
import matplotlib.pyplot as plt
histogram_data = np.random.rand(1000)
heatmap_data = np.random.rand(10, 100)
# Set up figure and axes
fig = plt.figure()
fig.suptitle("These are my two plots")
top_ax = fig.add_subplot(211) #2 rows, 1 col, 1st plot
bot_ax = fig.add_subplot(212) #2 rows, 1 col, 2nd plot
# This is the same as doing 'fig, (top_ax, bot_ax) = plt.subplots(2)'
# Histogram
weights = np.ones_like(histogram_data) / histogram_data.shape[0]
hist, bins = np.histogram(histogram_data, bins=50, weights=weights)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
# Use top_ax to modify anything with the histogram plot
top_ax.bar(center, hist, align='center', width=width)
# ax.text(x, y, str). Make sure x,y are within your plot bounds ((0, 1), (0, .5))
top_ax.text(0.5, 0.5, "Here is text on the top plot", color='r')
# Heatmap
heatmap_params = {'cmap':plt.cm.Blues, 'alpha':0.8, 'vmin':0, 'vmax':1}
# Use bot_ax to modify anything with the heatmap plot
heatmap = bot_ax.pcolor(heatmap_data, **heatmap_params)
cbar = fig.colorbar(heatmap, shrink=0.8, aspect=10, fraction=.1,pad=.01)
# See how it looks
plt.show()

Categories

Resources