How to create a create a concrete frame and animate that?

Hi.:smiley:
I need to animate a concrete frame moved by an earthquake.
So I have the coordinates of each initial and final node of each element (column or beam).
I then have to animate it by changing the coordinates of these nodes at each time interval.
I tried using Scatter3d, but the lines are drawn consecutively (which I donโ€™t want).

How can I trace these elements and then animate them?

@Zawardo To get an answer you should provide a use case, otherwise there are a lot of posibilities to animate a 3d plot.

1 Like

Im starting to create the 3d tensor(x= nodes, y = (dx,ty,tz), z= frames for 1 step of time) :

import plotly
import plotly.graph_objs as go

# Configure Plotly to be rendered inline in the notebook.
plotly.offline.init_notebook_mode()

# Configure the trace.
trace = go.Scatter3d(x=nodi[:,1,0],y=nodi[:,3,0],z=nodi[:,2,0],marker=dict(
        size=6,
        color=z,
        colorscale='Viridis',
    ),
    line=dict(
        color='darkblue',
        width=2
    ))
# Configure the layout.
layout = go.Layout(height=700,
    margin={'l': 0, 'r': 0, 'b': 0, 't': 0}
)

data = [trace]

plot_figure = go.Figure(data=data, layout=layout)

# Render the plot.
#plotly.offline.iplot(plot_figure)

This is result
newplot

Note the wrong connections between elements. For this i make other matrix for create correct element (x= element(beam, coulumn) , y = 1ยฐ)tag 2ยฐ)Initial node 3ยฐ) end node . THEN :

  1. How to draw correct frame ?
  2. How to refresh each step with new nodes coordinates?

@Zawardo

Here is how you animate 3d points in an interval of time [0,20], with time step=1:

import numpy as np
import plotly.graph_objs as go


nodi = 2*np.random.rand(30, 3)

trace = go.Scatter3d(x=nodi[:,0],y=nodi[:,1],z=nodi[:,2],
                      mode='markers',
                      marker=dict(size=6,
                      color= nodi[:, 2],
                      colorscale='Viridis'),
    )
# Configure the layout.
layout = go.Layout(width=600, height=600,
                  updatemenus=[dict(type='buttons', showactive=False,
                                y=1,
                                x=1.05,
                                xanchor='right',
                                yanchor='top',
                                pad=dict(t=0, r=10),
                                buttons=[dict(label='Play',
                                              method='animate',
                                              args=[None, 
                                                    dict(frame=dict(duration=500, 
                                                                    redraw=True),
                                                         transition=dict(duration=0),
                                                         fromcurrent=True,
                                                         mode='immediate')
                                                   ])
                                        ])])
                  

data = [trace]


#define frames:
t = np.linspace(0, 20, 21)
frames = [dict(data=[dict(type='scatter3d',
                         x=2*np.random.rand(30), 
                         y=2*np.random.rand(30), 
                         z=2*np.random.rand(30) )],
              name=k) for k in range(t.shape[0]) ]

fig = go.Figure(data=data, layout=layout, frames=frames)
fig.update_layout(scene =dict(xaxis= dict(range =[-1,3]), 
                              yaxis=dict(range =[-1,3]), 
                              zaxis=dict(range =[-1,3])
                 ))
fig.show()

to attach a slider that displays the time, just perform this update:

fig.update_layout(sliders=  [{'yanchor': 'top',
                              'xanchor': 'left', 
                              'currentvalue': {'font': {'size': 16}, 
                                               'prefix': 'Time: ', 
                                               'visible': True, 
                                               'xanchor': 'right'},
                              'transition': {'duration': 500.0, 'easing': 'linear'},
                              'pad': {'b': 10, 't': 50}, 
                              'len': 0.9, 'x': 0.1, 'y': 0, 
                              'steps': [{'args': [[k], {'frame': {'duration': 500.0, 'easing': 'linear', 'redraw': False},
                                      'transition': {'duration': 0, 'easing': 'linear'}}], 
                       'label': k, 'method': 'animate'} for k in range(t.shape[0])      
                    ]}])

PS: giving a use case means providing minimal data, too :slight_smile:

1 Like

thanks.
Now i do all but, i have 350 nodes to animate for 3000 step(frames). Code :

import plotly.graph_objs as go

fig = go.Figure()
# Configure the trace.
trace = go.Scatter3d(x=Elementi[:,0,0],y=Elementi[:,1,0],z=Elementi[:,2,0],marker=dict(
        size=4, color=z, colorscale='Viridis',), line=dict( color='darkblue', width=4 ))
data = [trace]

# Configure the layout.
layout = go.Layout(width=700, height=700,
    updatemenus=[dict(type='buttons', showactive=False,
    y=0, x=0.58, xanchor='right', yanchor='top', pad=dict(t=0, r=0),
    buttons=[dict(label='Play',method='animate',
    args=[None, dict(frame=dict(duration=500, redraw=True),
    transition=dict(duration=0),fromcurrent=True,mode='immediate')])])])

#define frames:
t = np.linspace(0, 20, 21)
frames = [dict(data=[dict(type='scatter3d',
    x=Elementi[:,0,ts], y=Elementi[:,1,ts], z=Elementi[:,2,ts] )],name=ts) 
    for ts in range(2000,Elementi.shape[2],100)]

fig = go.Figure(data=data, layout=layout, frames=frames)

fig.update_layout(sliders=  [{'yanchor': 'top','xanchor': 'left', 'currentvalue': 
    {'font': {'size': 16}, 'prefix': 'Time: ', 'visible': True, 'xanchor': 'right'},
    'transition': {'duration': 500.0, 'easing': 'linear'},'pad': {'b': 10, 't': 50}, 'len': 0.9, 'x': 0.1, 'y': 0, 
    'steps': [{'args': [[ts], {'frame': {'duration': 500.0, 'easing': 'linear', 'redraw': False},
    'transition': {'duration': 0, 'easing': 'linear'}}], 'label': ts, 'method': 'animate'} 
    for ts in range(2000,Elementi.shape[2],100) ]}])
fig.update_layout(scene = dict(
    xaxis = dict(dtick=2.5, range=[0,12], showgrid=False, zeroline=False,backgroundcolor='white'),
    yaxis = dict(dtick=2.5, range=[0,12], showgrid=False, zeroline=False,backgroundcolor='white'),
    zaxis = dict(dtick=3.0, range=[0,12], showgrid=False, zeroline=True,backgroundcolor='white'),))
fig.show()

Problem :
1)There are a method to lighten the animation. ?
2)fix axes position in the โ€œfigureโ€ ?
3) Create smooth animation ?
4) Stop animation ?
p.s.
How can i send the 3d tensor[528, 3, 3355]?.

@Zawardo

  1. You can insert lighting attribute into trace definitions that have such an attribute (surface, mesh3d) https://plot.ly/python/3d-surface-lighting/
    to check it just display help(go.ClassName.lighting).
    For example:
    help(go.Scatter3d.lighting) displays:
AttributeError                            Traceback (most recent call last)
<ipython-input-47-b0a4a859ad4b> in <module>
----> 1 help(go.Scatter3d.lighting)

AttributeError: type object 'Scatter3d' has no attribute 'lighting'
  1. to fix axes position set in xaxis, yaxis, zaxis the property autorange=True. In the case of given example, the motion of points create the impression of axes moving.

  2. For a smoother animation decrease frame duration in updatemenus, and transition duration in sliders.

  3. The animation stops when all the frames have been displayed.

  4. From my experience such a tensor is too big to be handled by plotly animation

Im recorded the bump of frame:
Build

How can fix the axes?
I set autorange = False because i want set manually the range of axes.

@Zawardo Address this question(โ€œHow to fix axesโ€) under the plotly.js category, because such an issue can be explained and fixed by the team working there.

ok. I will do this . ty