python pandas 3D voxel plot - python

I'm trying to use matplotlib to generate a 3D voxel plot of my spatial data to visualise where players go in my game.
This is the cube dataframe that I'm generating using the bounds of the game and placing a cube at regular intervals along each dimesion, with xyz describing the centre of each voxel and the offsets describing the bounds of each voxel. The value refers to the number of times a player entered that voxel so I can generate the heat map.
I'm currently using a scatter graph and that is working very well, but I want to be able to convert what I currently have into a voxel graph.
fig = matplotlib.pyplot.figure(figsize=(12, 12))
ax = fig.add_subplot(projection='3d')
print("Plotting")
ax.scatter(cubeDF['x'], cubeDF['y'], cubeDF['z'], c=cubeDF['value'], )
fig.show()
I'm sorry if this question is rushed but it's for my final year project and it's due in soon so I'm very stressed out about this whole thing

Related

Random (false data) lines appearing in contourf plot at certain # of levels

I'm trying to use matplotlib and contourf to generate some filled (polar) contour plots of velocity data. I have some data (MeanVel_Z_Run16_np) I am plotting on theta (Th_Run16) and r (R_Run16), as shown here:
fig,ax = plt.subplots(subplot_kw={'projection':'polar'})
levels = np.linspace(-2.5,4,15)
cplot = ax.contourf(Th_Run16,R_Run16,MeanVel_Z_Run16_np,levels,cmap='plasma')
ax.set_rmax(80)
ax.set_rticks([15,30,45,60])
rlabels = ax.get_ymajorticklabels()
for label in rlabels:
label.set_color('#E6E6FA')
cbar = plt.colorbar(cplot,pad=0.1,ticks=[0,3,6,9,12,15])
cbar.set_label(r'$V_{Z}$ [m/s]')
plt.show()
This generates the following plot:
Velocity plot with 15 levels:
Which looks great (and accurate), outside of that random straight orange line roughly between 90deg and 180deg. I know that this is not real data because I plotted this in MATLAB and it did not appear there. Furthermore, I have realized it appears to relate to the number of contour levels I use. For example, if I bump this code up to 30 levels instead of 15, the result changes significantly, with odd triangular regions of uniform value:
Velocity plot with 30 levels:
Does anyone know what might be going on here? How can I get contourf to just plot my data without these strange misrepresentations? I would like to use 15 contour levels at least. Thank you.

Turn data-labels in Plotly Polar Plot

Hi i have a dataset i am displaying in Plotly Polar.
However all the datalabels are horizontal, so they overlap each other and make it hard to read the plot.
Is there a way to have the data-labels turned so they are radially distributed?
df=file_from_xlsx
fig = px.scatter_polar(df, r="data", theta="Group", text="individual_data_label")
How can i turn the data labels, so they are in line with the theta angle already defined for the data points?
Thanks for your help!

Plotting an algorithm with interactive figure in Python

I want to visualise the effect of an algorithm that takes a 2d vector as input and delivers an array of 2d vectors as output (where the array has the k-th iteration value at index k).
The way I would like this to work is by having a 2d plot of a certain range of numbers on the left that represents the input vector, and a similar 2d plot on the right that plots the connected output vectors.
For an individual input point I know I could do this with matplotlib's plt.subplots() like this loosely adapted example from the documentation:
fig, axs = plt.subplots(2)
fig.suptitle('Vertically stacked subplots')
axs[0].plot(in_x, in_y)
axs[1].plot(out_array_x, out_array_y, 'o-')
But what I would like to do is to move the point on the input side with the mouse and get the resulting output on the right interactively. How could this be done?

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.

Matplotlib plot_surface: How to convert 1D arrays to required 2D input?

Maybe this question is a duplicate because I can imagine that many people face this problem. Forgive me if so.
I want to plot a sphere in Matplotlib 3D. For that, I have a bunch of xyz coordinates. When I plot it with plot_trisurf, I get this:
So I wanted to try plot_surface, but then I get the error ValueError: Argument Z must be 2-dimensional.
This post explains why the input for plot_surface is 2D.
My question ist: How can I convert my regular xyz coordinates into the format plot_surface needs?
Edit:
Okay, I understood that 3-tuples can be differently interpreted. Is there a way then to use plot_trisurf with some kind of polar coordinates, so that it doesn't interpolate "through the xy plane" but from the coordinate origin, spherically?
If your points are created in a mesh-like way, it is best to create mesh at the same time, such as in this post.
It seems plot_trisurf creates a mesh for an open surface (like a rectangular table cloth) but not for a closed surface.
If the points aren't nicely organized, but you know all points lie on a convex 3D surface (e.g. a sphere), you can calculate the 3D convex hull and draw that.
The code below does just that. Note that some triangles look darker and some lighter. This is because the triangles returned by ConvexHull aren't nicely oriented (so that e.g. a clockwise orientation would indicate the outside face of the polygon). For that you'd need to calculate the surface normal for each triangle and reverse the triangle in case the dot product of that normal with the center of the triangle would be negative (supposing 0,0,0 lies inside the sphere).
If you need more 3D plotting power, the Mayawi library would be more appropriate.
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.spatial import ConvexHull
import numpy as np
xyz = np.random.randn(3, 50) # random 3D points
xyz /= np.linalg.norm(xyz, axis=0) # project each point on a unit sphere
fig = plt.figure()
ax = fig.gca(projection='3d')
hull = ConvexHull(xyz.T)
ax.plot_trisurf(*xyz, triangles=hull.simplices, linewidth=0.2, antialiased=True)
plt.show()

Categories