I am trying to plot the following charts with Matpltlib:
I would like to have the colored dots at a constant distance from the bottom of the charts.
However as you can see they jump all over the place as their y coordinate is given in y value, and the y axis is different in each chart. Is there a way to define their y position in pixels from the x axis? Without having to resort to % of (top of the chart - bottom of the chart) would be ideal. Thanks!
You can plot the points in axes coordinates instead of data coordinates. Axes coordinates range from 0 to 1 (lower left corner to upper right corner).
In order to use axes coordinates, you need to supply Axes.transAxes to the plot's transform argument - also see the transformation tutorial.
Here is a minimal example:
import matplotlib.pyplot as plt
plt.plot([1,5,9], [456,894,347], "r-",
label="plot in data coordinates")
plt.plot([0.2,0.3,0.7], [0.2,0.2,0.5], "bo",
transform=plt.gca().transAxes, label="plot in axes coordinates")
plt.legend()
plt.show()
If you want to specify the horizontal coordinate in data coordinates, and the vertical one in axes coordinates, you can use a blended transformation,
matplotlib.transforms.blended_transform_factory(ax.transData, ax.transAxes)
This can be used as follows.
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
ax = plt.gca()
plt.plot([12,25,48], [456,894,347], "r-",
label="plot in data coordinates")
plt.plot([0.2,0.3,0.7], [0.2,0.2,0.5], "bo",
transform=ax.transAxes, label="plot in axes coordinates")
#blended tranformation:
trans = transforms.blended_transform_factory(ax.transData, ax.transAxes)
plt.plot([15,30,35], [0.75,0.25,0.5], "gs", markersize=12,
transform=trans, label="plot x in data-,\ny in axes-coordinates")
plt.legend()
plt.show()
Related
I'd like to create a continuous colormap with matplotlib on a 3D Surface Plot, where the color depends on the z-value of the surface. But with the "normal" plt functions the colormap fills the space between the gridpoints with the same color like shown in the picture. So there is no continuous change in color, rather there are just some colored surfaces stitched together:
x = range(0,126)
y = range(0,3)
#z is my data from the experiment
# make a grid of the x/y plane
X,Y= np.meshgrid(x,y)
# get the colormap for the graph
cmap=plt.get_cmap("RdBu")
# cmap = clr.LinearColormap.from_list('custom blue', ['#244162','#DCE6F1'], N=256)
#plot the corresponding z-value at every knot of the grid
surface = ax.plot_surface(X,Y,z, cmap = cmap, antialiased=True, edgecolor='gray' , linewidth=0.2)
m = cm.ScalarMappable(cmap=surface.cmap,norm=surface.norm)
m.set_array(z)
plt.colorbar(m)
ax.set_yticks(y)
ax.set_xticks(x[::25])
plt.show()
which looks like this:
3D-surface Plot
Do I need to interpolate the surface in between with more gridpoints, or is there a more elegant way? I'm a little lost in the documentation and syntax
Thanks in advance,
masterblibla
I am developing a python GUI that plots many lines, arrows and rectangles on a matplotlib canvas.
The rectangles go aligned with the lines: Rotated rectangle above line
Here is the picture.
I want to set a transform on the Rectangle, so that the side's length perpendicular to the line are in axes coordinates units (transAxes), and the sides parallel to the line are in data coordinates units (transData).
I know that blended_transform is can be used to define to different transforms for x-axis and y-axis. This is similar, but the directions in which the transforms are applied are not neccessary the horizontal and vertical direction. Is there a way of defining a custom blended transform that works on rotated directions instead of x-y directions? The documentation on transforms is not very helpful when trying to create a custom one.
Thanks!
The questions in the comments weren't answered, so one needs to make some assumptions. Let's say the rotation is supposed to happen in display space and the axes coordinates are those in y-axis direction. Then a possible transform could look like
trans = ax.get_xaxis_transform() + mtrans.Affine2D().rotate_deg(angle)
In this case the first dimension are data coordinates, the second are axes coordinates.
Some example:
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans
fig, ax = plt.subplots()
angle = 38 # degrees
trans = ax.get_xaxis_transform() + mtrans.Affine2D().rotate_deg(angle)
ax.plot([5,9],[0,0], marker="o", transform=trans)
rect = plt.Rectangle((5,0), width=4, height=0.2, alpha=0.3,
transform=trans)
ax.add_patch(rect)
ax.set(xlim=(3,10))
plt.show()
If instead you want rotation about a point in data coordinates, a single transform is not doing the job. For example for a rotation about (5,5) in data space,
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans
fig, ax = plt.subplots()
ax.set(xlim=(3,10),ylim=(4,10))
fig.canvas.draw()
angle = 38 # degrees
x, y = ax.transData.transform((5,5))
_, yax = ax.transAxes.inverted().transform((0,y))
transblend = ax.get_xaxis_transform()
x, y = transblend.transform((5,yax))
trans = transblend + mtrans.Affine2D().rotate_deg_around(x,y, angle)
ax.plot([5,9],[yax,yax], marker="o", transform=trans)
rect = plt.Rectangle((5,yax), width=4, height=0.2, alpha=0.3,
transform=trans)
ax.add_patch(rect)
plt.show()
Note that this invalidates as soon as you change the limits or figure size.
I want to mark a specific x-axis position with a colored asterisk drawn on top of the x-axis.
I use an x-tick label as the marker (because I couldn't figure out if it is possible to place markers anywhere in the fig coords) at it's aligned properly but is drawn below the x-axis so it's partially covered.
MWE:
import numpy as np
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,1)
ax.scatter([-1,1],[1,1])
ax.set_xticks([0],minor=True)
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=20,verticalalignment='center')
plt.setp(ax.spines.values(), linewidth=3)
plt.show()
That's what it looks like right now:
You can specify the coordinates of a scatter in a blended system (data coordinates for the y axis and axis coordinates for the x axis).
To then have the scatter marker above the spines set the zorder property of the scatter to something above 2.5.
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,1)
ax.scatter([-1,1],[1,1])
ax.scatter(0,0, s=100, marker="*", color="red",
transform=ax.get_xaxis_transform(), clip_on=False, zorder=3)
plt.show()
What you are looking for is zorder parameter. By using zorder = 0, you basically define the order of stacking of the plot sequence. 0 would send the axis/frame in the background putting the asterisk over the axis line as desired. I increased the size of the asterisk to highlight it.
ax.scatter([-1,1],[1,1])
ax.set_xticks([0],minor=True)
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=30,verticalalignment='center')
plt.setp(ax.spines.values(), linewidth=3, zorder=0)
Alternatively, you can also specify the zorder for both plotting commands but use a higher zorder for the asterisk
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=30,verticalalignment='center', zorder=2)
plt.setp(ax.spines.values(), linewidth=3, zorder=1)
I have a file with three columns, lets say, x y z. I need to plot x Vs y but I need to change the color of that (x,y) value depending on its density (stored in z column). I understand that I need to use color map and have to map the values of the color with the z array. I can do that via scatter plot as also shown in this post: How can I make a scatter plot colored by density in matplotlib?
But I do not need the scatter plot, I need the points to be connected, ie I need a line plot. Can it be done in line plot?
It's not possible to connect points from a scatter plot directly. But the same effect can be achieved by plotting a line behind the scatter points.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3,6)
y = np.sin(x)
z = 0.5+np.random.rand(len(x))
fig, ax = plt.subplots()
ax.plot(x, y, color="k", marker=None, zorder=0)
sc = ax.scatter(x, y, c=z, s=100, edgecolor='',zorder=3)
plt.colorbar(sc, label="Density")
plt.show()
I am using scatter plot in matplotlib to plot some points. I have two 1D arrays each storing the x and y coordinate of the samples. Also there is another 1D array that stores the label(to decide in which colour the point should be plotted). I programmed thus far:
import matplotlib.pyplot as plt
X = [1,2,3,4,5,6,7]
Y = [1,2,3,4,5,6,7]
label = [0,1,4,2,3,1,1]
plt.scatter(X, Y, c= label, s=50)
plt.show()
Now I want to be able to see which color corresponds to which label?
I looked up the implementation of legends in matplotlib like the one here:
how to add legend for scatter()?
However they are suggesting to create a plot for each label of sample. However all my labels are in the same 1D array(label). How can I achieve this?
You could do it with a colormap. Some examples of how to do it are here.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
X = [1,2,3,4,5,6,7]
Y = [1,2,3,4,5,6,7]
label = [0,1,4,2,3,1,1]
# Define a colormap with the right number of colors
cmap = plt.cm.get_cmap('jet',max(label)-min(label)+1)
bounds = range(min(label),max(label)+2)
norm = colors.BoundaryNorm(bounds, cmap.N)
plt.scatter(X, Y, c= label, s=50, cmap=cmap, norm=norm)
# Add a colorbar. Move the ticks up by 0.5, so they are centred on the colour.
cb=plt.colorbar(ticks=np.array(label)+0.5)
cb.set_ticklabels(label)
plt.show()
You might need to play around to get the tick labels centred on their colours, but you get the idea.