Need help displaying 4D data in matplotlib 3D scatterplot properly - matplotlib

Hey so I'm an undergraduate working in an imaging lab and I have a 3D numpy array that has values from 0-9 to indicate concentration in a 3D space. I'm trying to plot these values in a scatterplot with a colormap to indicate the value between 0-9. The array is 256 x 256 x 48, so I feel like the size of it is making it difficult for me to plot the array in a meaningful way.
I've attached a picture of what it looks like right now. As you can see the concentration looks very "faded" even for very high values and I'm not entirely sure why. Here is the code I'm using to generate the plot:
current heatmap
fig = plt.figure()
x, y, z = np.meshgrid(range(256), range(256), range(48))
col = sum_array.flatten()
ax = fig.add_subplot(111, projection = '3d')
sc = ax.scatter(x, y, z, c = col, cmap='Reds',
linewidths=.01, s=.03, vmin=0, vmax=9,
marker='.', alpha=1)
plt.colorbar(sc)
plt.show()
If anyone can help me display the colors in a more bright/concentrated manner so the heat map is visually useful, I'd really appreciate it. Thank you!

Related

plot irregular data with matplotlib

I have function data within a LinearNDInterpolator that I can evaluate using a meshgrid, and it looks pretty decent aside from some rendering glitches unique to the input data.
X, Y = np.meshgrid(x, y)
Z = interp(X, Y)
fig = plt.figure()
ax = plt.axes(projection="3d")
ax.plot_surface(X, Y, Z, cmap="viridis")
To work around the glitches I need to render the surface at a resolution that exceeds my resources. Also, the glitches are ameliorated when using triangular meshes. So I was hoping to plot the sparse data contained within the convex-hull without interpolating to a regular grid, which would waste memory. Unfortunately the resulting surface is a jumble of skinny triangles; a forest of broken glass. I was under the impression that LinearNDInterpolator simply interpolated the triangles without changing the mesh, so I'm wondering why the result is so poor.
qhull = interp.tri
mptri = mpl.tri.Triangulation\
( x = qhull.points[:, 0]
, y = qhull.points[:, 1]
, triangles = qhull.vertices
)
fig = plt.figure()
ax = plt.axes(projection="3d")
ax.plot_trisurf(mptri, interp.values, cmap="viridis")

Create 2D hanning, hamming, blackman, gaussian window in NumPy

I am interested in creating 2D hanning, hamming, Blackman, etc windows in NumPy. I know that off-the-shelf functions exist in NumPy for 1D versions of it such as np.blackman(51), np.hamming(51), np.kaiser(51), np.hanning(51), etc.
How to create 2D versions of them? I am not sure if the following solution is the correct way.
window1d = np.blackman(51)
window2d = np.sqrt(np.outer(window1d,window1d))
---EDIT
The concern is that np.sqrt expects only positive values while np.outer(window1d,window1d) will definitely have some negative values. One solution is to relinquish np.sqrt
Any suggestions how to extend these 1d functions to 2d?
That looks reasonable to me. If you want to verify what you are doing is sensible, you can try plotting out what you are creating.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 1.5, 51)
y = np.linspace(0, 1.5, 51)
window1d = np.abs(np.blackman(51))
window2d = np.sqrt(np.outer(window1d,window1d))
X, Y = np.meshgrid(x, y)
Z = window2d
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='viridis')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
plt.show()
This gives -
This looks like the 2d generalization of the 1d plot which looks like -
However, I had to do window1d = np.abs(np.blackman(51)) when creating the 1d version initially because otherwise, you would end up with small negative values in the final 2D array which you cannot take sqrt of.
Disclaimer: I am not familiar with the functions or their usual use-case. But the shapes of these plots seems to make sense. If the use-case of these functions is somewhere in which the actual values matter, this could be off.

3d plot with multiple lines showing the projection on the xy plane

I was wondering how to have a 3d plot with multiple lines showing the projection on the xy plane by means of something like fill_between but in 3D. I have here a sample code.
fig, ax = plt.subplots(figsize=(12,8),subplot_kw={'projection': '3d'})
for i in np.arange(0.0,1,0.1):
x1=np.arange(0,1-i+0.01,0.01)
y1=1.0-i-x1
def z_func(x,y,z):
return x+y**2+0.5*z #can be any fn
coordinates3= [[i,j,1-i-j] for j in np.arange(0,1-i+0.01,0.01)]
z1=np.array([z_func(*k) for k in coordinates3])
ax.plot(x1,y1,z1)
ax.view_init(azim=10,elev=20)
plt.show()
I'd like to have each line 'projected' on the xy plane, with a shaded filling in between the curve and its projection. Anybody knows a quick way?
After the suggestion in the comments of #ImportanceOfBeingErnest, I was able to write a solution. I came up with this:
fig, ax = plt.subplots(figsize=(12,8),subplot_kw={'projection': '3d'})
prop_cycle = plt.rcParams['axes.prop_cycle']
colors = prop_cycle.by_key()['color']
for color,i in enumerate(np.arange(0.0,1,0.1)):
x1=np.arange(0,1-i+0.01,0.01)
y1=1.0-i-x1
def z_func(x,y,z):
return x+y**2+0.5*z #can be any fn
coordinates3= [[i,j,1-i-j] for j in np.arange(0,1-i+0.01,0.01)]
z1=np.array([z_func(*k) for k in coordinates3])
verts=[[(k[1],k[2],z_func(*k)) for k in coordinates3]]
verts[0].insert(0,(coordinates3[0][1],coordinates3[0][2],0))
verts[0].insert(0,(coordinates3[-1][1],coordinates3[-1][2],0))
poly = Poly3DCollection(verts,color=colors[color])
poly.set_alpha(0.2)
ax.add_collection(poly)
ax.plot(x1,y1,z1,linewidth=10)
ax.view_init(azim=10,elev=20)
plt.show()
One thing that puzzles me is that the shade doesn't get the color of the line and that I had to supply it myself. If you remove the color=colors[color] in the Poly3DCollection you always get blue shades, whereas the lines automatically get the different colors, as one can see in the question. Anybody knows a reason for this?

Plot axvline from Point to Point in Matplotlib Python 3.6

I am reading Data from a Simulation out of an Excel File. Out of this Data I generated two DataFrames containing 200 values. Now i want to plot all the Values from DataFrame one in blue and all Values from DataFrame two in purple. Therefore I have following code:
df = pd.read_excel("###CENSORED####.xlsx", sheetname="Data")
unpatched = df["Unpatched"][:-800]
patched = df["Patched"][:-800]
x = range(0,len(unpatched))
fig = plt.figure(figsize=(10, 5))
plt.scatter(x, unpatched, zorder=10, )
plt.scatter(x, patched, c="purple",zorder=19,)
This results in following Graph:
But now i want to draw in some lines that visualize the difference between the blue and purple dots. I thought about an orange line going from blue dot at simulation-run x to the purple dot at simulation-run x. I've tried to "cheat" with following code, since I'm pretty new to matplotlib.
scale_factor = 300
for a in x:
plt.axvline(a, patched[a]/scale_factor, unpatched[a]/scale_factor, c="orange")
But this resulted in a inaccuracy as seen seen below:
So is there a smarter way to do this? I've realized that the axvline documentation only says that ymin, ymax can only be scalars. Can I somehow turn my given values into fitting scalars?

Pyplot polar surface plot

I am new in pyplot.
I have a Cartesian surface plot:
# offset and omega are arrays
Z = my_function(omega,offset) # my_function give and arrays of omega.size*offset.size
fig, ax = plt.subplots(1)
p = ax.pcolor(offset,omega,Z.T,cmap=cm.jet,vmin=abs(Z).min(),vmax=abs(Z).max())
cb = fig.colorbar(p,ax=ax)
Maybe there is a more simple way to plot a surface but that the way I've found on the internet.
Well, now I want to plot my_function as a surface using polar coordinate, I've tried this:
ax2 = plt.subplot(111, polar=True)
p2 = ax2.pcolor(offset,omega,Z.T,cmap=cm.jet,vmin=abs(Z).min(),vmax=abs(Z).max())
It kind of work, I have a surface plot but it does not take into account the limits of Y.
For example if Y is defined between -15 and 15° I only want my function to be plotted and shown between those angles and not 0 to 360° as my example is doing.
How can I do that ?
I thank you in advance for any answer.