BradyAJohnston / MolecularNodes

Toolbox for molecular animations in Blender, powered by Geometry Nodes.
https://bradyajohnston.github.io/MolecularNodes/
GNU General Public License v3.0
912 stars 85 forks source link

More options for MDAnalysis trajectory playback #441

Open BradyAJohnston opened 8 months ago

BradyAJohnston commented 8 months ago

Potential extra options to enable when streaming a trajectory from disk:

CeraveWasTakenLOL commented 2 months ago

@BradyAJohnston How do we offset the start frame?

BradyAJohnston commented 2 months ago

@CeraveWasTakenLOL I didn't end up explicitly adding this feature, as it can be achieved by changing the Start and End frame of the scene in inside of Blender. The Trajectory's frame will continue to match up with the frames inside of scene, but you can change the start and and of the scene to mimic the offset.

image

CeraveWasTakenLOL commented 1 month ago

@BradyAJohnston Changing the start and end frame will not work if you need to line up the beginnings of multiple MD trajectories or if you need to add it to an existing project (sometimes with hundreds of hard to access keyframes)

I ended up using this script which can offset the XTC file directly:

pip install MDAnalysis


import MDAnalysis as mda
from MDAnalysis.coordinates.XTC import XTCWriter

u = mda.Universe('topology.gro', 'input.xtc')
offset_frame_number = 56

with XTCWriter('output.xtc', n_atoms=u.atoms.n_atoms) as writer:
    first_frame = u.trajectory[0]
    for _ in range(offset_frame_number):
        writer.write(u.atoms)

    for ts in u.trajectory:
        ts.frame += offset_frame_number
        writer.write(u.atoms)
CeraveWasTakenLOL commented 1 month ago

On a side note, I also ended up using this script which can add subframes to certain parts of the XTC file (effectively slowing down or speeding up specific parts of the animation)



import MDAnalysis as mda
from MDAnalysis.coordinates.XTC import XTCWriter
import numpy as np

u = mda.Universe("processed.gro", "combined_centered.xtc")

frame_start = 35
frame_end = 37
n_subframes = 10  

output_xtc = 'interpolated_frames_full.xtc'

with XTCWriter(output_xtc, n_atoms=u.atoms.n_atoms) as xtc_writer:
    for ts in u.trajectory[:frame_start]:
        xtc_writer.write(u.atoms)

    positions_start = u.trajectory[frame_start].positions.copy()
    positions_end = u.trajectory[frame_end].positions.copy()
    time_start = u.trajectory[frame_start].time
    time_end = u.trajectory[frame_end].time

    u.trajectory[frame_start]
    xtc_writer.write(u.atoms)

    for i in range(1, n_subframes + 1):
        alpha = i / (n_subframes + 1)  
        interpolated_positions = (1 - alpha) * positions_start + alpha * positions_end
        interpolated_time = (1 - alpha) * time_start + alpha * time_end

        u.trajectory.ts.positions = interpolated_positions
        u.trajectory.ts.time = interpolated_time

        xtc_writer.write(u.atoms)

    u.trajectory[frame_end]
    xtc_writer.write(u.atoms)

    for ts in u.trajectory[frame_end+1:]:
        xtc_writer.write(u.atoms)

print(f"Interpolated frames saved to {output_xtc}")
BradyAJohnston commented 1 month ago

I hadn't considered wanting to sync up multiple trajectories in a single file. Should be able to add it without too much trouble. Adding certain subframes to certain areas is still something probably best handled externally like you are doing in your script there, which is a good example of how to do it

CeraveWasTakenLOL commented 1 month ago

Here's another script for offsetting in the opposite direction (deleting frames as opposed to duplicating the first frame)

I don't have any experience with creating Blender add-ons but if there's anything I can do to help let me know


import MDAnalysis as mda
from MDAnalysis.coordinates.XTC import XTCWriter

u = mda.Universe("topology.pdb", "trajectory.xtc")
frames_to_remove = 50

with XTCWriter("output.xtc", n_atoms=u.atoms.n_atoms) as w:
    for ts in u.trajectory[50:]:
        w.write(u.atoms)
BradyAJohnston commented 1 month ago

Thanks for the scripts @CeraveWasTakenLOL !

I'll take a slightly different approach - I won't actually be modifying the universe / trajectory at all. Inside of Blender we can just map all of the frames before the offset value to the first frame and then all of the rest with the offset :)

BradyAJohnston commented 1 month ago

This is now addressed in #608