3D Pointcloud Plot - python

got some Issues here, I do have Coordinates in lists. These coordinates are from a Laserscanner, which scans in layers, so finished one layer it gets to the next, this is were the indicies and nested lists come from. The single lists for X Y and Z are 720 indices long. And the descriebed earlier nested lists for every indice are representing the layers. This gives me a Structure like shown here:
len(X) = 720
X[1] = [ 0. 8.62348279 ... 9.10556606 9.15339632 9.11527918 9.11995584]
What did i try until now?
I did try to plot this Stuff as a Scatterplot, which works quite fine.
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for i in range(len(X1)):
plt.scatter(X1[i],Y1[i],Z1[i],marker='x')
plt.show()
Now on to my questions:
The ScatterPlot, which you see implemented above shows the points in
a strange "gluLookAt" condition, my first question is how to manipulate
the Look At Angle or Position. So I´m watching the Plot like I´am in the
Position of the scanner, or a bit above.
How can I plot the single Layers in different colors, there are 24 Layers
for one scan circle.
In addition to show how the scanner works, it would be nice to have an
animated scan profile, so every layer get´s scanned one after another.
I hope you guys can help me again, Thanks in advance.
Best regards

Related

Contour line error with plt.contour in python 3

I am plotting a contour plot in python 3 with matplotlib, and I am getting a strange result. At first, I was using plt.contourf, and notices there was a strange north-south linear artifact in the data that I knew shouldn't be there (I used simulated data). So I changed plt.contourf to plt.contour, and the problem seems to be that some of the edge contours are deformed for some reason (see picture).
Unfortunately, it is hard for me to past a simple version of my code because this is part of a large GUI based app. Here is what I am doing though.
#grid the x,y,z data so it can be used in the contouring
self.beta_zi =
#This is matplot griddata, not the scipy.interpolate.griddata
griddata(self.output_df['x'].values,self.output_df['y'].values,
self.output_df['Beta'].values,
self.cont_grid_x,
self.cont_grid_y,
interp='linear')
#call to the contour itself
self.beta_contour=self.beta_cont_ax.contour(self.cont_grid_x,self.cont_grid_y,
self.beta_zi,
levels=np.linspace(start=0,stop=1, num=11, endpoint=True),
cmap=cm.get_cmap(self.user_beta_cmap.get()))
This seems like a simple problem based on the edges. Has anyone seen this before that can help. I am use a TK backend, which works better with the tkinter based GUI I wrote.
UPDATE: I also tried changing to scipy.interpolate.griddata because matplot's griddata is deprecated, but the problem is the same and persists, so it must be with the actual contour plotting function.
I found that the problem had to do with how I was interpreting the inputs of contour and grid data.
plt.contour and matplot.griddata takes
x = x location of sample data
y = y location of sample data
z = height or z value of sample data
xi = locations of x tick marks on grid
zi = locations of y ticks marks on grid
Typically xi and yi are all the locatoins of each grid node, which is what I was supplying, but in this case you only need the unqiue tick marks on each axis.
Thanks to this post I figured it out.
Matplotlib contour from xyz data: griddata invalid index

3D scatter color by categorical (x,y) coordinates?

I am trying to make the scatter dots have the same color if they have the same (x,y) values but with a different Z value.
so far I managed to use one variable either x or y, but I cant "zip" them together somehow.
df["X"]=pd.Categorical(df["X"])
df["Y"]=pd.Categorical(df["Y"])
df["X"].cat.codes
df["Y"].cat.codes
bx.scatter(xs,ys,zs, zdir=zs, c=df["X"].cat.codes,cmap="Set1", alpha=1)
I tried to zip them individually, I tried making an array out of them...If I try with
df["cat"]=pd.Categorical(zip(df["X"],df["Y"]))
df["cat"].cat.codes
all I get is one category code, so everything is the same.
Any ideas?
image for clarification
At first I thought the dates should be the category, but that doesnt makes sense because every day ( since the Zaxes is in datetime format) would have a different a color.
Insstead, every possible (x,y) pair ie. (1,-1), (2,1) etc should be a category(is it the right word to use?) by itself so then every pair should have its own color for example (1,-1) is black, (2,1) is red independently of its Z coordinate.
the solution was quite easy in fact, it just took some tinkering round
Original DF has X,Y,Date columns.
xs=df.X
ys=df.Y
zs=np.array(df_dates2num)
N=len(df)
val_x=df["X"].tolist()
val_y=df["Y"].tolist()
df["pairs"]=pd.Series(list(zip(val_x,val_y)), index=df.index) #make(x,y) pairs
df["pairs"]=df["pairs"].astype("category")
df["pairs"]=df.pairs.cat.codes
bx.scatter(xs,ys,zs, zdir=zs, c=df["pairs"], alpha=1, s=50) #scatter dots
and it actually works, the only thing missing is to use a more discrete color palette.

Colour between the rings on a python radar graph

I'm rather new to coding and i'm currently stuck on this problem.
I am trying to shade the region from 0-2 on the radar graph and have been using
ax.fill(x_as, values3, color="#757575", alpha=0.3)
where i set values 3 as 2.
However, this creates a hexagon rather than a smooth shading from 0-2.
Not sure if there is a simple way of solving this, but any input would be useful!
Cheers
Current radar graph
Without seeing your code, it is hard to be sure, but most likely you are only using 6 different values in x_as -- the same values you use for your line plots. If instead you use a more densely populated array, say with 100 values, your fill area will appear to be circular:
thetas = np.linspace(0,2*np.pi,100)
ax.fill(thetas, [2 for i in thetas], color = "#757575", alpha = 0.3)
Below a figure with some arbitrary data for the line plots and the above given code for the shaded area:
Hope this helps.

Possible to use a custom arrow or polygon as a marker to plot location and heading in matplotlib?

I have a series of x,y coordinates and associated heading angles for multiple aircraft. I can plot the paths flown, and I would like to use a special marker to mark a particular location along the path that also shows the aircraft's heading when it was at that location.
Using matplotlib.pyplot I've used an arrowhead with no base to do this, but having to define the head and tail locations ended up with inconsistent arrowhead lengths when plotting multiple aircraft. I also used a custom three-sided symbol with the tuple (numsides, style, angle) as well as the wedge and bigvee symbols, but they never look very good.
From Custom arrow style for matplotlib, pyplot.annotate Saullo Castro showed a nice custom arrow (arrow1) that I'm wondering whether it can be used or converted in such a way as to just simply plot it at a given x,y and have its orientation defined by a heading angle.
I can plot the custom arrow with the following. Any ideas on how to rotate it to reflect a heading?
a1 = np.array([[0,0],[0,1],[-1,2],[3,0],[-1,-2],[0,-1],[0,0]], dtype=float)
polB = patches.Polygon(a1, closed=True, facecolor='grey')
ax.add_patch(polB)
Thanks in advance.
So I made the polygon a little simpler and also found that the rotation could be done by using mpl.transforms.Affine2D().rotate_deg_around():
a2 = np.array([[newX,newY+2],[newX+1,newY-1],[newX,newY],[newX-1,newY-1],[newX,newY+2]], dtype=float)
polB = patches.Polygon(a2, closed=True, facecolor='gold')
t2 = mpl.transforms.Affine2D().rotate_deg_around(newX,newY,heading) + newax.transData
polB.set_transform(t2)
newax.add_patch(polB)
I first tried to overlay the polygon on a line plotted from the x,y coordinates. However, the scales of the x and y axes were not equal (nor did I want them to be), so the polygon ended up looking all warped and stretched when rotated. I got around this by first adding a new axis with equal x/y scaling:
newax = fig.add_axes(ax.get_position(), frameon=False)
newax.set_xlim(-20,20)
newax.set_ylim(-20,20)
I could at least then rotate all I wanted and not have the warp issue. But then I needed to figure out how to basically connect the two axes so that I could plot the polygon on the new axis at a point referenced from the original axis. The way I figured to do this was by using transformations to go from the data coordinates on the original axis, converting them to display coordinates, and then inverting them back to data coordinates except this time at the data coordinates on the new axis:
inTrans = ax.transData.transform((x, y))
inv = newax.transData.inverted()
newTrans = inv.transform((inTrans[0], inTrans[1]))
newX = newTrans[0]
newY = newTrans[1]
It felt a little like some sort of Rube Goldberg machine to do it this way, but it did what I wanted.
In the end, I decided I didn't like this approach and went with keeping it simpler and using a fancy arrowhead instead of a polygon. Such is life...

Opacity misleading when plotting two histograms at the same time with matplotlib

Let's say I have two histograms and I set the opacity using the parameter of hist: 'alpha=0.5'
I have plotted two histograms yet I get three colors! I understand this makes sense from an opacity point of view.
But! It makes is very confusing to show someone a graph of two things with three colors. Can I just somehow set the smallest bar for each bin to be in front with no opacity?
Example graph
The usual way this issue is handled is to have the plots with some small separation. This is done by default when plt.hist is given multiple sets of data:
import pylab as plt
x = 200 + 25*plt.randn(1000)
y = 150 + 25*plt.randn(1000)
n, bins, patches = plt.hist([x, y])
You instead which to stack them (this could be done above using the argument histtype='barstacked') but notice that the ordering is incorrect.
This can be fixed by individually checking each pair of points to see which is larger and then using zorder to set which one comes first. For simplicity I am using the output of the code above (e.g n is two stacked arrays of the number of points in each bin for x and y):
n_x = n[0]
n_y = n[1]
for i in range(len(n[0])):
if n_x[i] > n_y[i]:
zorder=1
else:
zorder=0
plt.bar(bins[:-1][i], n_x[i], width=10)
plt.bar(bins[:-1][i], n_y[i], width=10, color="g", zorder=zorder)
Here is the resulting image:
By changing the ordering like this the image looks very weird indeed, this is probably why it is not implemented and needs a hack to do it. I would stick with the small separation method, anyone used to these plots assumes they take the same x-value.

Categories

Resources