Matplotlib Color Gradient based on y-value - python

I would like to plot a "cut" through a heat map, i.e. apply a color gradient to my plt.plot(x,y) based on the y-values (which are in a range of -0.5,0.5.
Any suggestions? I tried to workaround by using a scatter-plot, but the colormap seemed to be applied to each line individually (and not globally).
Thanks!
EDIT
To describe it in other terms: I would like to map each y-value in the interval to an appropriate color in my colormap. (The phrase 'cut through heat map' just refers to the commonly used technique to map the z-values of a function z=f(x,y) for given x and y to a color.)
As mentioned earlier already, just applying a colormap to a scatter-plot seems to to map the maximum y-value of each line (as i am plotting multiple series) to white, as seen in the attachment. Instead, I would like to map the global y=0.5 in my plot to white and -0.5 to black for each line.

Turns out i needed to normalize my colormap by using
norm = colors.Normalize(vmin=-min, vmax=max)
and then call plt.scatter(x, y, c=y, norm=norm, …).

Related

Contour Plot of Binary Data (0 or 1)

I have x values, y values, and z values. The z values are either 0 or 1, essentially indicating whether an (x,y) pair is a threat (1) or not a threat (0).
I have been trying to plot a 2D contour plot using the matplotlib contourf. This seems to have been interpolating between my z values, which I don't want. So, I did a bit of searching and found that I could use pcolormesh to better plot binary data. However, I am still having some issues.
First, the colorbar of my pcolormesh plot doesn't show two distinct colors (white or red). Instead, it shows a full spectrum from white to red. See the attached plot for what I mean. How do I change this so that the colorbar only shows two colors, for 0 and 1? Second, is there a way to draw a grid of squares into the contour plot so that it is more clear for which x and y intervals the 0s and 1s are occurring. Third, my code calls for minorticks. However, these do not show up in the plot. Why?
The code which I use is shown here. The vels and ms for x and y can really be anything, and the threat_bin is just the corresponding 0 or 1 values for all the (vets,ms) pairs:
fig=plt.figure(figsize=(6,5))
ax2=fig.add_subplot(111)
from matplotlib import cm
XX,YY=np.meshgrid(vels, ms)
cp=ax2.pcolormesh(XX/1000.0,YY,threat_bin, cmap=cm.Reds)
ax2.minorticks_on()
ax2.set_ylabel('Initial Meteoroid Mass (kg)')
ax2.set_xlabel('Initial Meteoroid Velocity (km/s)')
ax2.set_yscale('log')
fig.colorbar(cp, ticks=[0,1], label='Threat Binary')
plt.show()
Please be simple with your recommendations, and let me know the code I should include or change with respect to what I have at the moment.

Creating a pseudo color plot with a linear and nonlinear axis and computing values based on the center of grid values

I have the equation: z(x,y)=1+x^(2/3)y^(-3/4)
I would like to calculate values of z for x=[0,100] and y=[10^1,10^4]. I will do this for 100 points in each axis direction. My grid, then, will be 100x100 points. In the x-direction I want the points spaced linearly. In the y-direction I want the points space logarithmically.
Were I to need these values I could easily go through the following:
x=np.linspace(0,100,100)
y=np.logspace(1,4,100)
z=np.zeros( (len(x), len(y)) )
for i in range(len(x)):
for j in range(len(y)):
z[i,j]=1+x[i]**(2/3)*y[j]**(-3/4)
The problem for me comes with visualizing these results. I know that I would need to create a grid of points. I feel my options are to create a meshgrid with the values and then use pcolor.
My issue here is that the values at the center of the block do not coincide with the calculated values. In the x-direction I could fix this by shifting the x-vector by half of dx (the step between successive values). I'm not so sure how I would do this for the y-axis. Furthermore, If I wanted to compute values for each of the y-direction values, including the end points, they would not all show up.
In the final visualization I would like to have the y-axis as a log scale and the x axis as a linear scale. I would also like the tick marks to fall in the center of the cells, correlating with the correct value. Can someone point me to the correct plotting functions for this. I have to resolve the issue using pcolor or pcolormesh.
Should you require more details, please let me know.
In current matplotlib, you can use pcolormesh with shading='nearest', and it will center the blocks with the values:
import matplotlib.pyplot as plt
y_plot = np.log10(y)
z[5, 5] = 0 # to make it more evident
plt.pcolormesh(x, y_plot, z, shading="nearest")
plt.colorbar()
ax = plt.gca()
ax.set_xticks(x)
ax.set_yticks(y_plot)
plt.axvline(x[5])
plt.axhline(y_plot[5])
Output:

Add labels ONLY to SELECTED data points in seaborn scatter plot

I have created a seaborn scatter plot and added a trendline to it. I have some datapoints that fall very far away from the trendline (see the ones highlighted in yellow) so I'd like to add data labels only to these points, NOT to all the datapoints in the graph.
Does anyone know what's the best way to do this?
So far I've found answers to "how to add labels to ALL data points" (see this link) but this is not my case.
In the accepted answer to the question that you reference you can see that the way they add labels to all data points is by looping over the data points and calling .text(x, y, string) on the axes. You can find the documentation for this method here (seaborn is implemented on top of matplotlib). You'll have to call this method for the selected points.
In your specific case I don't know exactly what formula you want to use to find your outliers but to literally get the ones beyond the limits of the yellow rectangle that you've drawn you could try the following:
for x,y in zip(xarr, yarr):
if x < 5 and y > 5.5:
ax.text(x+0.01, y, 'outlier', horizontalalignment='left', size='medium', color='black')
Where xarr is your x-values, yarr your y-values and ax the returned axes from your call to seaborn.

How to create a 3d Heatmap from a discrete data set in Python?

I have a large dataset of the form [(X1, Y1, Z1, VALUE1), (X2, Y2, Z2, VALUE2)...]. The geometry of the points is the surface of a cylinder, while there are many discrete points they come nowhere near being a full mesh.
I would like to create a basic plot, where each of the points is given an intensity of a color (like a heatmap) based on how high its value is, and then the colors are smoothed to some degree to create a cohesive surface rather than discrete points
I am currently using matplotlib, however, I would also use other libraries if necessary.
I have looked into both surface plots and Tri-Surface plots but neither seem to do what I want (although the documentation for plot_trisurf() is a little confusing so maybe it is still a possibility).
I have also looked at this post: 3D discrete heatmap in matplotlib.
And while the set up is mostly the same, I would like to have a more cohesive surface plot rather than a 3d Tetris set up. The original answer seems pretty close to my desired solution, however, I would like the colors to be based on VALUE rather than Z and if possible for there to be color smoothing between the sections.
Depending on how dense your point cloud is you may be able to get what you want with this (adjust the size parameter, s, to fill out the plot best for your data):
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(X, Y, Z, c=Value, lw=0, s=20)
plt.show()

Matplotlib contour map colorbar

I am plotting my data into a contour map. The computations work on the translated values, so I need to put it back to its original value. On the fourth line of the code, is the re-translation process.
However, when I plotted it the colorbar shows the relative values, and just a note of the shift value at the top of the color bar. It is just weird that I checked the matrix values, and it contains the original values.
How can I show the colorbar, with the original values displayed?
fig=plt.figure()
v=np.linspace(-180,180,25)
x,y = np.meshgrid(v,v)
z = np.add(z,-shift)
z = z.reshape(25,25).T
plt.contourf(x,y,z,25)
fig.suptitle(AA(prefix)+' Input Data Contour Map')
plt.xlabel('$\phi$ (deg)')
plt.ylabel('$\psi$ (deg)')
plt.xticks(np.arange(-180, 181, 30))
plt.yticks(np.arange(-180, 181, 30))
plt.colorbar()
UPDATE: I used set_ticklabels() for a temporary fix, where labels is a list of custom labels.
But I am still looking for a better way to solve this problem.
plt.colorbar().set_ticklabels(labels)
updated contour map
Matplotlib doesn't know about your shift variable. It is choosing to plot it that way because the changes you are trying to visualize are 10^(-6) of the background value.
You can force the colorbar to have tick marks at specific locations as they do in this pylab example using:
cbar = fig.colorbar(cax, ticks=[-1, 0, 1])
cbar.ax.set_yticklabels(['< -1', '0', '> 1']) # vertically oriented colorbar
However, doing so will make the scale very difficult to read.

Categories