enthought / mayavi

3D visualization of scientific data in Python
http://docs.enthought.com/mayavi/mayavi/
Other
1.28k stars 282 forks source link

Animation freezes unexpectedly #1283

Open spoty76 opened 8 months ago

spoty76 commented 8 months ago

I'm running an animation that displays orbital trajectory of a probe using two dimensional array with position vectors. All the physics is pre-calculated before animation, which results in an array called frameBasedPos with x y z positions corresponding to column 0, 1, 2 and rows corresponding to frames to draw. I am also drawing a sphere of the planet with texture, and a trailing trajectory.

Here is a video: keep in mind that len(frameBasedPos) indicates how many seconds the animation will run since every row (frame) corresponds to 1 second worth of simulation. mlab(delay) is calculated using constants, it is basically becomes a constant integer of 10. https://github.com/enthought/mayavi/assets/41343898/0816854c-b85b-4193-b48b-70b76cb53a78

The issue is that the animation stops working around similar iteration times depending on the circumstances, it can either be around 1156 or different.

I tried removing the sphere and trajectory, it doesn't solve the issue, just changes when it gets stuck. Force rendering and frocing gui doesn't help either. When I remove elements it seems to get stuck at a later frame.

The nature of freeze is also mysterious. The gui that mayavi creates by default to start stop animation disappears. Python drops CPU resources to 0, memory is kept occupied. I have Ryzen 9 5900x, rtx2080super, 64gb ram, which should be enough, and there is barely any resources used when performing the animation. I tried wrapping animation into try: exception:, there are no hidden exceptions occuring. No errors output. When I debug it it seems that when it finally reaches the frame where it's about to freeze, it completes the animation update function, but doesn't yield to next frame, indicating that potentially VTK gets stuck.

Here is my code for the animation. frameBasedPos is a completely correct array with 100 000 total rows, but the animation breaks either around frame 1156 or 2450 and the numbers aren't exact, it can break at different frame around the same region.

`fig = mlab.figure(size=(1920, 1080), bgcolor=(1, 1, 1))

Planet: code source: https://stackoverflow.com/questions/53074908/map-an-image-onto-a-sphere-and-plot-3d-trajectories

sphere = mlab.points3d(0, 0, 0, scale_factor=2*R, color=(1, 0.5, 0), resolution=10) image_file = 'C:\Users\DDL\Desktop\OrbitalTrajectory\VENUSsurface.jpg'

load and map the texture

img = tvtk.JPEGReader() img.file_name = image_file texture = tvtk.Texture(input_connection=img.output_port, interpolate=1)

(interpolate for a less raster appearance when zoomed in)

use a TexturedSphereSource, a.k.a. getting our hands dirty

Nrad = 180

create the sphere source with a given radius and angular resolution

sphere = tvtk.TexturedSphereSource(radius=R, theta_resolution=Nrad, phi_resolution=Nrad)

assemble rest of the pipeline, assign texture

sphere_mapper = tvtk.PolyDataMapper(input_connection=sphere.output_port) sphere_actor = tvtk.Actor(mapper=sphere_mapper, texture=texture)

Rotate the planet for correct axis allignment

transform = tvtk.Transform()

transform.rotate_x(90)

transform.rotate_z(90)

transform.rotate_z(90)

sphere_actor.user_transform = transform

Apply this transform to the sphere_actor

sphere_actor.user_transform = transform

fig.scene.add_actor(sphere_actor)

probeObj = mlab.points3d([0], [0], [0], scale_factor=1e5, color=(1, 0, 0)) text_display = mlab.text(0.1, 0.9, '', width=0.6, color=(0,0,0)) mlab.plot3d([0, 0], [0, 0], [-R1.5, R1.5], color=(0, 0, 1), tube_radius=0.01R) # Blue color for Z-axis mlab.text3d(0, 0, R1.6, 'Z+', scale=(0.05R, 0.05R, 0.05R), color=(0, 0, 1)) mlab.plot3d([-R1.5, R1.5], [0, 0], [0, 0], color=(1, 0, 0), tube_radius=0.01R) # Red color for X-axis mlab.text3d(R1.6, 0, 0, 'X+', scale=(0.05R, 0.05R, 0.05R), color=(1, 0, 0)) mlab.plot3d([0, 0], [-R1.5, R1.5], [0, 0], color=(0, 1, 0), tube_radius=0.01R) # Red color for X-axis mlab.text3d(0, R1.6, 0, 'Y+', scale=(0.05R, 0.05R, 0.05*R), color=(0, 1, 0))

Trajectory trail setting

trajectoryOn = True if trajectoryOn: trajectory_length = 700 # Trailing length trajectory_line = mlab.plot3d([0]trajectory_length, [0]trajectory_length, [0]*trajectory_length, color=(0, 1, 0), tube_radius=10e3)

def update_scene(num):

# Get the current position

xPos, yPos, zPos = frameBasedPos[num]
alt = frameBasedAlt[num]

if trajectoryOn:
    # Update trajectory
    startID = max(0, num - trajectory_length + 1)  # Start index
    endID = num + 1  # End index is the current frame
    x_traj = frameBasedPos[startID:endID, 0]
    y_traj = frameBasedPos[startID:endID, 1]
    z_traj = frameBasedPos[startID:endID, 2]
    if len(x_traj) < trajectory_length: # Draw along point limit
        x_traj = np.pad(x_traj, (trajectory_length - len(x_traj), 0), 'constant', constant_values=x_traj[0])
        y_traj = np.pad(y_traj, (trajectory_length - len(y_traj), 0), 'constant', constant_values=y_traj[0])
        z_traj = np.pad(z_traj, (trajectory_length - len(z_traj), 0), 'constant', constant_values=z_traj[0])
    trajectory_line.mlab_source.set(x=x_traj, y=y_traj, z=z_traj) # Update

# Update probe position
probeObj.mlab_source.set(x=[xPos], y=[yPos], z=[zPos])

# Update time and altitude display
text_str = f"Time: {frameBasedTimes[num]:.0f}s Altitude: {alt:.2f}km"
text_display.text = text_str

# Force render the scene
#fig.scene.render()

Animation framer initialization

@mlab.show @mlab.animate(delay=int(displayEvery1000animationScaler)) def anim(): n = 0 # Frame skipper: zero if from the start for i in range(n, len(frameBasedPos)):

    update_scene(i)

    #mlab.process_ui_events()

    yield    # Resume frames from left of last frame
    #mlab.process_ui_events()

anim()`

Import section: import numpy as np from scipy.interpolate import interp1d import matplotlib.pyplot as plt from mayavi import mlab from tvtk.api import tvtk import pandas as pd