Figure with multiple traces in subplots - python

I'm trying to create a plot containing 3 subplots, each subplot containing a number of lines plus 2 threshold lines. So far I'm able to create the subplots and plot a couple of lines, but when I want to add more than 2 lines, it won't display them.
Here is the code I'm using:
# Make many subplots
for p_i in range(poses_values_array.shape[1]-6):
if p_i%3 == 0:
main_fig = subplots.make_subplots(rows=3, cols=1, subplot_titles=("lLeg","rLeg","Hip"))
fig = go.Figure()
# Treshold lines
fig.add_trace(go.Scatter(x= list(range(poses_values_array.shape[2])),
y= [pose_max[p_i]] * poses_values_array.shape[2],
name=f'Max Pose {pose_motion[p_i%3]} {pose_names[int(p_i/3)]} Threshold'))
fig.add_trace(go.Scatter(x= list(range(poses_values_array.shape[2])),
y= [pose_min[p_i]] * poses_values_array.shape[2],
name=f'Min Pose {pose_motion[p_i%3]} {pose_names[int(p_i/3)]} Threshold'))
# Data
for t_i in range(poses_values_array.shape[0]):
fig.add_trace(go.Scatter(x=list(range(len(poses_values_array[t_i, p_i, :]))),
y=poses_values_array[t_i, p_i, :],
name=f'Target {t_i+1} - Pose {pose_motion[p_i%3]} {pose_names[int(p_i/3)]}'))
fig.update_layout(title=f'Pose {p_i}',
xaxis_title='Dataset',
yaxis_title='Pose Value')
fig.update_yaxes(autorange=False, zeroline=True, zerolinewidth=2, zerolinecolor='LightPink')
# Update the subplots
for i in range (poses_values_array.shape[0]):
main_fig.append_trace(fig.data[i], row=(p_i%3)+1, col=1)
main_fig.update_layout(title=f'Aggregated {pose_names[int(p_i/3)]} Pose {p_i}-{p_i+3}')
# Update subplots individual subtitles
main_fig.layout.annotations[p_i%3].update(text=f"{pose_names[int(p_i/3)]} {pose_motion[p_i%3]} Pose")
I also tried placing the Threshold lines after the for loop that plots Data, resulting in my current 2 lines (will have more actually) of data showing up but not the treshold lines.
I tried too using fig.add_hline() with the same result.
This is what results from the code. Ideally I would like to see the t_i lines of data in between the thresholds lines:
Hope I can get a hint of what I'm doing wrong.
Thanks!

Oh, wow, soon after posting this question, giving another read to my code, I found the error.
I was not taking into account the threshold lines as part of fig.data, so I was only looping through the first 2 traces that were added to it on the # Update subplots line. I just had to switch for i in range (poses_values_array.shape[0]) to for i in range (poses_values_array.shape[0]+2).

Related

3D Pointcloud Plot

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

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.

Reshape data into 'closest square'

I'm fairly new to python. Currently using matplotlib I have a script that returns a variable number of subplots to make, that I pass to another script to do the plotting. I want to arrange these subplots into a nice arrangement, i.e., 'the closest thing to a square.' So the answer is unique, let's say I weight number of columns higher
Examples: Let's say I have 6 plots to make, the grid I would need is 2x3. If I have 9, it's 3x3. If I have 12, it's 3x4. If I have 17, it's 4x5 but only one in the last row is created.
Attempt at a solution: I can easily find the closest square that's large enough:
num_plots = 6
square_size = ceil(sqrt(num_plots))**2
But this will leave empty plots. Is there a way to make the correct grid size?
This what I have done in the past
num_plots = 6
nr = int(num_plots**0.5)
nc = num_plots/nr
if nr*nc < num_plots:
nr+=1
fig,axs = pyplot.subplots(nr,nc,sharex=True,sharey=True)
If you have a prime number of plots like 5 or 7, there's no way to do it unless you go one row or one column. If there are 9 or 15 plots, it should work.
The example below shows how to
Blank the extra empty plots
Force the axis pointer to be a 2D array so you can index it generally even if there's only one plot or one row of plots
Find the correct row and column for each plot as you loop through
Here it is:
nplots=13
#find number of columns, rows, and empty plots
nc=int(nplots**0.5)
nr=int(ceil(nplots/float(nc)))
empty=nr*nc-nplots
#make the plot grid
f,ax=pyplot.subplots(nr,nc,sharex=True)
#force ax to have two axes so we can index it properly
if nplots==1:
ax=array([ax])
if nc==1:
ax=ax.reshape(nr,1)
if nr==1:
ax=ax.reshape(1,nc)
#hide the unused subplots
for i in range(empty): ax[-(1+i),-1].axis('off')
#loop through subplots and make output
for i in range(nplots):
ic=i/nr #find which row we're on. If the definitions of ir and ic are switched, the indecies for empty (above) should be switched, too.
ir=mod(i,nr) #find which column we're on
axx=ax[ir,ic] #get a pointer to the subplot we're working with
axx.set_title(i)

Heatmap with varying y axis

I would like to create a visualization like the upper part of this image. Essentially, a heatmap where each point in time has a fixed number of components but these components are anchored to the y axis by means of labels (that I can supply) rather than by their first index in the heatmap's matrix.
I am aware of pcolormesh, but that does not seem to give me the y-axis functionality I seek.
Lastly, I am also open to solutions in R, although a Python option would be much preferable.
I am not completely sure if I understand your meaning correctly, but by looking at the picture you have linked, you might be best off with a roll-your-own solution.
First, you need to create an array with the heatmap values so that you have on row for each label and one column for each time slot. You fill the array with nans and then write whatever heatmap values you have to the correct positions.
Then you need to trick imshow a bit to scale and show the image in the correct way.
For example:
# create some masked data
a=cumsum(random.random((20,200)), axis=0)
X,Y=meshgrid(arange(a.shape[1]),arange(a.shape[0]))
a[Y<15*sin(X/50.)]=nan
a[Y>10+15*sin(X/50.)]=nan
# draw the image along with some curves
imshow(a,interpolation='nearest',origin='lower',extent=[-2,2,0,3])
xd = linspace(-2, 2, 200)
yd = 1 + .1 * cumsum(random.random(200)-.5)
plot(xd, yd,'w',linewidth=3)
plot(xd, yd,'k',linewidth=1)
axis('normal')
Gives:

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