Open BradyAJohnston opened 8 months ago
@BradyAJohnston How do we offset the start frame?
@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.
@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)
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}")
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
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)
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 :)
This is now addressed in #608
Potential extra options to enable when streaming a trajectory from disk:
u.select_atoms(updating = True)
(#501, #466)option for computing bonds in MDAnlysis when importing