From 6bd14c9204d0642ffb6f8c06a03e78264dc49d99 Mon Sep 17 00:00:00 2001 From: John Chodera Date: Mon, 10 Jul 2017 20:48:24 -0600 Subject: [PATCH 1/4] Add movie-making scripts --- movies/README.md | 21 +++++ movies/render_trajectory.py | 165 ++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 movies/README.md create mode 100644 movies/render_trajectory.py diff --git a/movies/README.md b/movies/README.md new file mode 100644 index 0000000..f2cf5c5 --- /dev/null +++ b/movies/README.md @@ -0,0 +1,21 @@ +# Create a movie from a protons trajectory + +Create a conda environment +```bash +conda create -n pymol -c mw pymol netcdf4 mdtraj +``` + +Launch pymol: +```bash +pymol +``` + +Run `render_trajectory.py` within pymol: +```bash +run render_trajectory.py +``` + +Render the frames into a movie: +```bash +ffmpeg -r 30 -i png/frame%05d.png -r 15 -b:v 5000000 -f mp4 -vcodec h264 -pix_fmt yuv420p -y movie.mp4 +``` \ No newline at end of file diff --git a/movies/render_trajectory.py b/movies/render_trajectory.py new file mode 100644 index 0000000..d126d69 --- /dev/null +++ b/movies/render_trajectory.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python + +""" +Render a protons trajectory with PyMOL +""" + +#============================================================================================= +# IMPORTS +#============================================================================================= + +import numpy as np +#import Scientific.IO.NetCDF +import netCDF4 as NetCDF +import os, shutil +import os.path +from pymol import cmd +from pymol import util +import mdtraj + +# try to keep PyMOL quiet +#cmd.set('internal_gui', 0) +#cmd.feedback("disable","all","actions") +#cmd.feedback("disable","all","results") + +#============================================================================================= +# PARAMETERS +#============================================================================================= + +system = 'imatinib' # 'imatinib' +png_dir = 'png' # BE CAREFUL: This directory will be removed every time you run this + +if system == 'imatinib': + prefix = 'GBAOAB/Imatinib-solvent' + netcdf_filename = '%s/Imatinib-solvent.nc' % prefix + trajectory_filename = '%s/Imatinib-solvent.dcd' % prefix + reference_pdb_filename = '%s/imatinib-solvated-for-calibration.pdb' % prefix +else: + raise Exception('System %s unrecognized' % system) + +if os.path.exists(png_dir): + shutil.rmtree(png_dir) +os.makedirs(png_dir) + +#============================================================================================= +# SUBROUTINES +#============================================================================================= + +#============================================================================================= +# MAIN +#============================================================================================= + +#import __main__ +#__main__.pymol_argv = [ 'pymol', '-qc'] +#import pymol +#pymol.finish_launching() + +# Read chemical identities +print("Reading identities from '%s'..." % netcdf_filename) +ncfile = NetCDF.Dataset(netcdf_filename, 'r') +# atom_index[residue,atom] is the 0-indexed index of atom 'atom' in residue 'residue' +# this is a masked array +atom_index = ncfile['/Protons/Metadata/atom_index'][:,:] +# atom_status[iteration,residue,atom] is the status of atom (residue,atom) at time 'iteration' +# 0 - deprotonated +# 1 - protonated +# 255 - this atom does not exist in atom_index[residue,atom] so don't look it up since it will be masked +atom_status = ncfile['/Protons/Titration/atom_status'][:,:,:] +[nframes, nresidues, natoms] = atom_status.shape +print('There are %d frames for %d titratable residues' % (nframes, nresidues)) +ncfile.close() + +# Read PDB file into MDTraj +print('Reading trajectory into mdtraj...') +traj = mdtraj.load(reference_pdb_filename) + +# Reset +cmd.rewind() +cmd.delete('all') +cmd.reset() + +# Load PDB file into PyMOL +cmd.set('suspend_updates', 'on') +cmd.load(reference_pdb_filename, 'system') +cmd.hide('all') +cmd.select('water', 'resn HOH or resn WAT or resn NA or resn CL') +cmd.select('solute', 'not water') +cmd.deselect() + +#cmd.show('cartoon', 'solute') +#cmd.color('white', 'solute') + +# speed up builds +cmd.set('defer_builds_mode', 3) +cmd.set('cache_frames', 0) +cmd.cache('disable') +cmd.set('async_builds', 1) + +cmd.set('ray_transparency_contrast', 3.0) +cmd.set('ray_transparency_shadows', 0) + +model = cmd.get_model('system') +#for atom in model.atom: +# print "%8d %4s %3s %5d %8.3f %8.3f %8.3f" % (atom.index, atom.name, atom.resn, int(atom.resi), atom.coord[0], atom.coord[1], atom.coord[2]) + +#pymol.finish_launching() + +cmd.viewport(640,480) +#niterations = 10 # DEBUG + +# Load trajectory +cmd.load_traj(trajectory_filename, object='system') + +# Delete waters +cmd.remove('water') + +# Align all states +cmd.intra_fit('solute') # protein + +# Zoom viewport +cmd.orient('solute') +cmd.zoom('solute') + +# Create one-to-one mapping between states and frames. +cmd.mset("1 -%d" % nframes) + + +# Delete first frame +cmd.mdelete("1") + +#cmd.orient('solute') +util.cbaw('solute') +cmd.show('spheres', 'solute') # DNA + +# Render movie +#cmd.set('ray_trace_frames', 1) +#nframes = 2 +for frame in range(nframes): + print "rendering frame %04d / %04d" % (frame+1, nframes) + cmd.set('suspend_updates', 'on') + cmd.frame(frame+1) # update frames + # Determine proton indices that should be on and off + active_protons = list() + inactive_protons = list() + + cmd.show('spheres', 'solute') + for residue in range(nresidues): + for atom in range(natoms): + if atom_status[frame,residue,atom] == 0: + inactive_protons.append(atom_index[residue,atom] + 1) + elif atom_status[frame,residue,atom] == 1: + active_protons.append(atom_index[residue,atom] + 1) + active_selection = 'index ' + '+'.join([str(index) for index in active_protons]) + inactive_selection = 'index ' + '+'.join([str(index) for index in inactive_protons]) + #cmd.show('spheres', inactive_selection) + #cmd.show('spheres', active_selection) + cmd.set('sphere_transparency', 0.8, inactive_selection) + cmd.set('sphere_transparency', 0.0, active_selection) + + last_inactive_protons = inactive_protons + last_active_protons = active_protons + + filename = os.path.join(png_dir, 'frame%05d.png' % frame) + print(filename) + cmd.set('suspend_updates', 'off') + cmd.png(filename) From f725aee3d1ea08fccc2b1f85f6f8cce10efc8d18 Mon Sep 17 00:00:00 2001 From: John Chodera Date: Mon, 10 Jul 2017 23:13:09 -0600 Subject: [PATCH 2/4] Fix bug in pymol atom selection --- movies/render_trajectory.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/movies/render_trajectory.py b/movies/render_trajectory.py index d126d69..ff4595e 100644 --- a/movies/render_trajectory.py +++ b/movies/render_trajectory.py @@ -149,12 +149,12 @@ inactive_protons.append(atom_index[residue,atom] + 1) elif atom_status[frame,residue,atom] == 1: active_protons.append(atom_index[residue,atom] + 1) - active_selection = 'index ' + '+'.join([str(index) for index in active_protons]) - inactive_selection = 'index ' + '+'.join([str(index) for index in inactive_protons]) - #cmd.show('spheres', inactive_selection) + active_selection = 'id ' + '+'.join([str(index) for index in active_protons]) + inactive_selection = 'id ' + '+'.join([str(index) for index in inactive_protons]) #cmd.show('spheres', active_selection) - cmd.set('sphere_transparency', 0.8, inactive_selection) - cmd.set('sphere_transparency', 0.0, active_selection) + cmd.hide('spheres', inactive_selection) + #cmd.set('sphere_transparency', 0.8, inactive_selection) + #cmd.set('sphere_transparency', 0.0, active_selection) last_inactive_protons = inactive_protons last_active_protons = active_protons From 6a9a9e5d35700847ffecdd95f6d28beeb7d7ebbe Mon Sep 17 00:00:00 2001 From: John Chodera Date: Tue, 11 Jul 2017 23:01:38 -0600 Subject: [PATCH 3/4] Updates to movie script for imatinib in solvent --- movies/render_trajectory.py | 67 ++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/movies/render_trajectory.py b/movies/render_trajectory.py index ff4595e..ea9ccf0 100644 --- a/movies/render_trajectory.py +++ b/movies/render_trajectory.py @@ -27,6 +27,7 @@ #============================================================================================= system = 'imatinib' # 'imatinib' +#system = 'abl-imatinib-full' # 'imatinib' png_dir = 'png' # BE CAREFUL: This directory will be removed every time you run this if system == 'imatinib': @@ -34,6 +35,11 @@ netcdf_filename = '%s/Imatinib-solvent.nc' % prefix trajectory_filename = '%s/Imatinib-solvent.dcd' % prefix reference_pdb_filename = '%s/imatinib-solvated-for-calibration.pdb' % prefix +elif system == 'abl-imatinib-full': + prefix = 'GBAOAB/Abl-Imatinib-full' + netcdf_filename = '%s/Abl-Imatinib-full.nc' % prefix + trajectory_filename = '%s/Abl-Imatinib-full.dcd' % prefix + reference_pdb_filename = '%s/2HYY-H.pdb' % prefix else: raise Exception('System %s unrecognized' % system) @@ -129,37 +135,80 @@ #cmd.orient('solute') util.cbaw('solute') -cmd.show('spheres', 'solute') # DNA +cmd.show('spheres', 'solute') # Render movie #cmd.set('ray_trace_frames', 1) -#nframes = 2 +#nframes = 100 +npause = 30 +output_frame = 0 +cmd.set('suspend_updates', 'off') +last_active_protons = list() +last_inactive_protons = list() + for frame in range(nframes): print "rendering frame %04d / %04d" % (frame+1, nframes) - cmd.set('suspend_updates', 'on') cmd.frame(frame+1) # update frames # Determine proton indices that should be on and off active_protons = list() inactive_protons = list() - cmd.show('spheres', 'solute') + #cmd.show('spheres', 'solute') + #cmd.set('sphere_transparency', 0.0) for residue in range(nresidues): for atom in range(natoms): if atom_status[frame,residue,atom] == 0: inactive_protons.append(atom_index[residue,atom] + 1) elif atom_status[frame,residue,atom] == 1: active_protons.append(atom_index[residue,atom] + 1) + + appear_set = set(active_protons).intersection(last_inactive_protons) + disappear_set = set(inactive_protons).intersection(last_active_protons) + active_selection = 'id ' + '+'.join([str(index) for index in active_protons]) inactive_selection = 'id ' + '+'.join([str(index) for index in inactive_protons]) + + appear_selection = 'id ' + '+'.join([str(index) for index in appear_set]) + disappear_selection = 'id ' + '+'.join([str(index) for index in disappear_set]) + + if frame == 0: + cmd.set('sphere_transparency', 0, active_selection) + cmd.set('sphere_transparency', 1, inactive_selection) + + if len(disappear_set) > 0: + for pause_frame in range(npause): + cmd.set('sphere_transparency', float(pause_frame+1)/float(npause), disappear_selection) + filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) + cmd.png(filename) + output_frame += 1 + #cmd.show('spheres', active_selection) - cmd.hide('spheres', inactive_selection) + #cmd.hide('spheres', inactive_selection) + #cmd.set('sphere_transparency', 0.0) #cmd.set('sphere_transparency', 0.8, inactive_selection) #cmd.set('sphere_transparency', 0.0, active_selection) + if len(appear_set) > 0: + for pause_frame in range(npause): + cmd.set('sphere_transparency', 1.0 - float(pause_frame+1)/float(npause), appear_selection) + filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) + cmd.png(filename) + output_frame += 1 + + #if nchange > 0: + # for pause_frame in range(npause): + # filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) + # cmd.png(filename) + # output_frame += 1 + # cmd.set('stick_transparency', 1.0 - float(pause_frame+1)/float(nframes), disappear_selection) + # cmd.set('stick_transparency', float(pause_frame+1)/float(nframes), appear_selection) + + last_inactive_protons = inactive_protons last_active_protons = active_protons - filename = os.path.join(png_dir, 'frame%05d.png' % frame) - print(filename) - cmd.set('suspend_updates', 'off') - cmd.png(filename) + if len(appear_set) + len(disappear_set) == 0: + filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) + cmd.set('suspend_updates', 'off') + cmd.png(filename) + output_frame += 1 From 013191ecb4570dcefe0d3f27a717298cf54a4454 Mon Sep 17 00:00:00 2001 From: John Chodera Date: Mon, 17 Jul 2017 20:47:30 -0400 Subject: [PATCH 4/4] Update scripts and README --- movies/README.md | 21 +++- movies/render_ncmc_switching_trajectory.py | 136 +++++++++++++++++++++ movies/render_trajectory.py | 93 ++++++++------ 3 files changed, 214 insertions(+), 36 deletions(-) create mode 100644 movies/render_ncmc_switching_trajectory.py diff --git a/movies/README.md b/movies/README.md index f2cf5c5..0bff480 100644 --- a/movies/README.md +++ b/movies/README.md @@ -10,12 +10,29 @@ Launch pymol: pymol ``` -Run `render_trajectory.py` within pymol: +Run `render_trajectory.py` within `pymol`: ```bash run render_trajectory.py ``` +or, to generate a movie from a single NCMC switch within `pymol`, +```bash +run render_ncmc_switching_trajectory.py +``` +Note that you will need to edit the parameters at the top of the script, such as: +``` +prefix = 'GBAOAB/Imatinib-solvent' +netcdf_filename = '%s/Imatinib-solvent.nc' % prefix +trajectory_filename = '%s/Imatinib-solvent.dcd' % prefix +reference_pdb_filename = '%s/imatinib-solvated-for-calibration.pdb' % prefix +``` +or use the presets provided. Render the frames into a movie: ```bash ffmpeg -r 30 -i png/frame%05d.png -r 15 -b:v 5000000 -f mp4 -vcodec h264 -pix_fmt yuv420p -y movie.mp4 -``` \ No newline at end of file +``` +If this complains that your movie is not 640x480, something went wrong during the rendering and the viewport dimensions changed away from 640x480. Reset this in `pymol` within +``` +cmd.viewport(640,480) +``` +and try again. diff --git a/movies/render_ncmc_switching_trajectory.py b/movies/render_ncmc_switching_trajectory.py new file mode 100644 index 0000000..9e395cf --- /dev/null +++ b/movies/render_ncmc_switching_trajectory.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +""" +Render a protons trajectory with PyMOL +""" + +#============================================================================================= +# IMPORTS +#============================================================================================= + +import numpy as np +#import Scientific.IO.NetCDF +import netCDF4 as NetCDF +import os, shutil +import os.path +from pymol import cmd +from pymol import util +import mdtraj + +# try to keep PyMOL quiet +#cmd.set('internal_gui', 0) +#cmd.feedback("disable","all","actions") +#cmd.feedback("disable","all","results") + +#============================================================================================= +# PARAMETERS +#============================================================================================= + +trajectory_filename = 'NCMC_trajectory.dcd' +reference_pdb_filename = 'imatinib-solvated-for-calibration.pdb' +atom_name = 'HN48' +png_dir = 'png' +nframes = 10001 + +if os.path.exists(png_dir): + shutil.rmtree(png_dir) +os.makedirs(png_dir) + +#============================================================================================= +# SUBROUTINES +#============================================================================================= + +#============================================================================================= +# MAIN +#============================================================================================= + +# Read PDB file into MDTraj +print('Reading trajectory into mdtraj...') +traj = mdtraj.load(reference_pdb_filename) +topology = traj.topology + +# Find the proton +atom_index = None +for atom in topology.atoms: + if atom.name == atom_name: + atom_index = atom.index +print(atom_index) + +# Reset +cmd.rewind() +cmd.delete('all') +cmd.reset() + +# Load PDB file into PyMOL +cmd.load(reference_pdb_filename, 'system') +cmd.hide('all') +cmd.select('water', 'resn HOH or resn WAT or resn NA or resn CL') +cmd.select('solute', 'not water and not name HN51') +cmd.select('proton', 'name %s' % atom_name) +cmd.select('nearby_water', 'water within 12 of proton') +cmd.deselect() + +#cmd.show('cartoon', 'solute') +#cmd.color('white', 'solute') + +# speed up builds +cmd.set('defer_builds_mode', 3) +cmd.set('cache_frames', 0) +cmd.cache('disable') +cmd.set('async_builds', 1) + +cmd.set('ray_transparency_contrast', 3.0) +cmd.set('ray_transparency_shadows', 0) + +cmd.viewport(640,480) +#niterations = 10 # DEBUG + +# Load trajectory +cmd.load_traj(trajectory_filename, object='system') + +# Align all states +cmd.intra_fit('solute') # protein + +# Zoom viewport +cmd.orient('solute') +cmd.zoom('proton', +5) + +# Create one-to-one mapping between states and frames. +cmd.mset("1 -%d" % nframes) + + +# Delete first frame +cmd.mdelete("1") + +#cmd.orient('solute') +#cmd.show('sticks', 'protein') +cmd.show('sticks', 'nearby_water') +#cmd.show('sticks', 'water') +cmd.show('spheres', 'solute') +util.cbay('solute') + +# Render movie +#cmd.set('ray_trace_frames', 1) +npause = 30 +output_frame = 0 + +def set_sphere_transparency(selection, value): + for atom_index in selection: + cmd.set('sphere_transparency', value, 'id %d' % (atom_index+1)) + +output_frame = 0 +#nframes = 90 +cmd.viewport(640,480) +for frame in range(0,nframes,10): + print "rendering frame %04d / %04d" % (frame+1, nframes) + cmd.frame(frame+1) # update frames + # Determine proton indices that should be on and off + active_protons = list() + inactive_protons = list() + + value = float(frame+1) / float(nframes) + set_sphere_transparency([atom_index], value) + + filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) + cmd.png(filename) + output_frame += 1 diff --git a/movies/render_trajectory.py b/movies/render_trajectory.py index ea9ccf0..e2c8169 100644 --- a/movies/render_trajectory.py +++ b/movies/render_trajectory.py @@ -27,7 +27,7 @@ #============================================================================================= system = 'imatinib' # 'imatinib' -#system = 'abl-imatinib-full' # 'imatinib' +system = 'abl-imatinib-full' # 'imatinib' png_dir = 'png' # BE CAREFUL: This directory will be removed every time you run this if system == 'imatinib': @@ -78,6 +78,26 @@ # Read PDB file into MDTraj print('Reading trajectory into mdtraj...') traj = mdtraj.load(reference_pdb_filename) +topology = traj.topology + +# Find all atom indices bonded to protons in titratable sites +print('Building table of atoms bonded to protons...') +proton_indices = set() # MDTraj zero-indexed proton indices +for residue in range(nresidues): + for atom in atom_index[residue,:].compressed(): + proton_indices.add(atom) +atoms = [atom for atom in topology.atoms] +bonded_atoms = dict() +for (atom1, atom2) in topology.bonds: + if (atom1.element == mdtraj.element.hydrogen): + bonded_atoms[atom1.index] = atom2.index + if (atom2.element == mdtraj.element.hydrogen): + bonded_atoms[atom2.index] = atom1.index + +titratable_residues = set() +for residue in range(nresidues): + for atom in atom_index[residue,:].compressed(): + titratable_residues.add(atoms[atom].residue.resSeq) # Reset cmd.rewind() @@ -90,6 +110,9 @@ cmd.hide('all') cmd.select('water', 'resn HOH or resn WAT or resn NA or resn CL') cmd.select('solute', 'not water') +cmd.select('ligand', 'resn STI') +cmd.select('protein', 'solute and not resn STI') +cmd.select('titratable', 'resi ' + '+'.join([str(resSeq+1) for resSeq in titratable_residues])) cmd.deselect() #cmd.show('cartoon', 'solute') @@ -123,8 +146,8 @@ cmd.intra_fit('solute') # protein # Zoom viewport -cmd.orient('solute') -cmd.zoom('solute') +cmd.orient('ligand') +cmd.zoom('ligand') # Create one-to-one mapping between states and frames. cmd.mset("1 -%d" % nframes) @@ -134,8 +157,11 @@ cmd.mdelete("1") #cmd.orient('solute') -util.cbaw('solute') -cmd.show('spheres', 'solute') +#cmd.show('sticks', 'protein') +cmd.show('sticks', 'titratable') +cmd.show('spheres', 'ligand') +util.cbag('protein') +util.cbay('ligand') # Render movie #cmd.set('ray_trace_frames', 1) @@ -146,7 +172,19 @@ last_active_protons = list() last_inactive_protons = list() -for frame in range(nframes): +def set_sphere_transparency(selection, value): + for atom_index in selection: + if atoms[atom_index].element == mdtraj.element.hydrogen: + cmd.set('sphere_transparency', value, 'id %d' % (atom_index+1)) + +def set_stick_transparency(selection, value): + for atom1_index in selection: + if atoms[atom1_index].element == mdtraj.element.hydrogen: + atom2_index = bonded_atoms[atom1_index] + cmd.set_bond('stick_transparency', value, 'id %d' % (atom1_index+1), 'id %d' % (atom2_index+1)) + +#nframes = 30 +for frame in range(nframes-1): print "rendering frame %04d / %04d" % (frame+1, nframes) cmd.frame(frame+1) # update frames # Determine proton indices that should be on and off @@ -158,57 +196,44 @@ for residue in range(nresidues): for atom in range(natoms): if atom_status[frame,residue,atom] == 0: - inactive_protons.append(atom_index[residue,atom] + 1) + inactive_protons.append(atom_index[residue,atom]) elif atom_status[frame,residue,atom] == 1: - active_protons.append(atom_index[residue,atom] + 1) + active_protons.append(atom_index[residue,atom]) appear_set = set(active_protons).intersection(last_inactive_protons) disappear_set = set(inactive_protons).intersection(last_active_protons) - active_selection = 'id ' + '+'.join([str(index) for index in active_protons]) - inactive_selection = 'id ' + '+'.join([str(index) for index in inactive_protons]) - - appear_selection = 'id ' + '+'.join([str(index) for index in appear_set]) - disappear_selection = 'id ' + '+'.join([str(index) for index in disappear_set]) - if frame == 0: - cmd.set('sphere_transparency', 0, active_selection) - cmd.set('sphere_transparency', 1, inactive_selection) + set_sphere_transparency(active_protons, 0) + set_sphere_transparency(inactive_protons, 1) + set_stick_transparency(active_protons, 0) + set_stick_transparency(inactive_protons, 1) if len(disappear_set) > 0: + print('disappear: %s' % disappear_set) for pause_frame in range(npause): - cmd.set('sphere_transparency', float(pause_frame+1)/float(npause), disappear_selection) + value = float(pause_frame+1)/float(npause) + set_sphere_transparency(disappear_set, value) + set_stick_transparency(disappear_set, value) filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) cmd.png(filename) output_frame += 1 - #cmd.show('spheres', active_selection) - #cmd.hide('spheres', inactive_selection) - #cmd.set('sphere_transparency', 0.0) - #cmd.set('sphere_transparency', 0.8, inactive_selection) - #cmd.set('sphere_transparency', 0.0, active_selection) - if len(appear_set) > 0: + print('appear: %s' % appear_set) for pause_frame in range(npause): - cmd.set('sphere_transparency', 1.0 - float(pause_frame+1)/float(npause), appear_selection) + value = 1.0 - float(pause_frame+1)/float(npause) + set_sphere_transparency(appear_set, value) + set_stick_transparency(appear_set, value) filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) cmd.png(filename) output_frame += 1 - #if nchange > 0: - # for pause_frame in range(npause): - # filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) - # cmd.png(filename) - # output_frame += 1 - # cmd.set('stick_transparency', 1.0 - float(pause_frame+1)/float(nframes), disappear_selection) - # cmd.set('stick_transparency', float(pause_frame+1)/float(nframes), appear_selection) - - last_inactive_protons = inactive_protons last_active_protons = active_protons if len(appear_set) + len(disappear_set) == 0: filename = os.path.join(png_dir, 'frame%05d.png' % output_frame) - cmd.set('suspend_updates', 'off') + #cmd.set('suspend_updates', 'off') cmd.png(filename) output_frame += 1