Making Movies with the Explode Operator

This page will cover details on making movies using VisIt's explode operator. This article does not cover the basics of making a movie in VisIt or the basics of using the explode operator. For basic movie making information, visit Making Movies. For an introduction to the explode operator, visit Explode Operator

About this Guide

The primary intent of this guide is to provide users with a detailed template script for creating movies using the explode operator. Below, you will find this template script along with a couple examples of seeing this script in use and the movies generated from these examples. The template script itself is filled with notes to help guide users through each step of the movie making process.

Example Movies

The following links contain examples of movies created by using VisIt's explode operator. The remainder of this guide will be referencing these examples.

Movie Template

The following template is intended to be a simple guideline used for creating explode operator movies. Of course, this template does not cover all possibilities, but it will likely cover most needs and should, at the very least, be a good starting point for creating even more advanced scripts. You will notice that some areas of this script are filled out for you, while other areas need attention. All areas that need attention are marked in the following fashion:

#FIXME: action needed
#*******************************
#<starter_code>
#*******************************

Where <starter_code> is replaced by some hint as to what should be written.

Template Script

##########################################################
# Author: Alister Maguire
# Date: Tue Mar 13 10:59:22 PDT 2018
#
# This script is meant to act as a guide for making movies
# with the Explode Operator. This guide does not go over 
# details specific to making movies in general. For 
# information about making movies in general, there are 
# several guides available through visitusers.org
#
##########################################################

from visit_utils import *

#
# Open your database.
#
#FIXME: action needed
#*******************************
#OpenDatabase(<your_database>)
#*******************************

#
# Remove the window annotations.
#
annotationAtts = AnnotationAttributes()
annotationAtts.axes2D.visible = 0
annotationAtts.axes3D.visible = 0
annotationAtts.axes3D.triadFlag = 0
annotationAtts.axes3D.bboxFlag = 0
annotationAtts.userInfoFlag = 0
annotationAtts.databaseInfoFlag = 0
annotationAtts.legendInfoFlag = 0
SetAnnotationAttributes(annotationAtts)

#
# Create the attributes for saving windows.
#
swatts = SaveWindowAttributes()
swatts.family = 0
swatts.format = swatts.PNG 
swatts.width = 1024 
swatts.height = 1024

#
# Add a plot and change whatever plot attributes you'd like to change. 
#
#FIXME: action needed
#*******************************
#AddPlot(<Plot>, <var>)
#*******************************

#
# Add the explode operator, and retrieve an instance of 
# the Explode Attributes. This instance of the attributes
# will be the operator's primary source for exposions. As
# you will see, all future instances of Explode Attributes 
# will be added to this one. 
#
AddOperator("Explode")
main_atts = ExplodeAttributes()
#FIXME: action needed
#*******************************
#num_exp   =  # number of explosions desired
#*******************************


#
# The next section is dedicated to creating 'helper
# lists', which just help in creating explosions later.
# All of these lists are of size num_exp, and the ith
# index corresponds to the ith explosion. For instance,
# helper_list[0] would retrieve data for the first
# explosion, and helper_list[13] would retrieve data
# for the 14th explosion.  
#

#
# Create a list of material names which correspond to 
# explosion indicies. For instance, mat_names[0] will
# contain the material used in the 0th (first) explosion. 
#
#FIXME: action needed
#*******************************
#mat_names = 
#*******************************

#
# Create two separate lists here. The first will contain 
# the initial factors of each explosion. The second will
# contain the amount of change to apply after each iteration
# or movie frame. Applying these changes to their corresponding
# factors is what results in objects being gradually exploded
# away from (or towards) their origins over time. 
#
#FIXME: action needed
#*******************************
#factors   =  
#change    = 
#*******************************



#
# For convenience, you can create lists 
# of pre-calculated explode origins. 
#
#FIXME: action needed
#*******************************
#planes =    # create lists where each element is of the form
#            # (planePoint, planeNorm) or [planePoint, planeNorm].
#
#points =    # create a list of explosion points that are used.  
#
#cylinders = # create a list where each element is of the form 
#            # (point1, point2, radius) or [point1, point2, radius].
#*******************************

#
# Create a list of explosion types. This will map each explosion 
# index to its type. 
#
#FIXME: action needed
#*******************************
#exp_types = 
#*******************************

#
# Create a list which signifies whether an explosion is a material
# explosion, material cell explosion, or full cell explosin.  
#
#FIXME: action needed
#*******************************
#cell_exp = 
#*******************************


#
# Here's where you create the actual explosions. 
#
for exp_idx in range(num_exp):
    #
    # Retrieve a new instance of Explode Attributes and 
    # set its type. 
    #
    exp = ExplodeAttributes()
    exp.explosionType = exp_types[exp_idx]

    #
    # Set the explosion type for each material. 
    #
    if exp.explosionType == exp.Point:
        exp.explosionPoint = points[exp_idx]

    if exp.explosionType == exp.Plane:
        exp.planePoint = planes[exp_idx][0]
        exp.planeNorm  = planes[exp_idx][1]

    if exp.explosionType == exp.Cylinder:
        exp.cylinderPoint1 = cylinders[exp_idx][0]
        exp.cylinderPoint2 = cylinders[exp_idx][1]
        exp.cylinderRadius = cylinders[exp_idx][2]
        
    if cell_exp[exp_idx] == 'MAT_CELL_EXP':
        exp.materialExplosionFactor = 0
        exp.explodeMaterialCells    = 1
        exp.cellExplosionFactor     = factors[exp_idx]
    elif cell_exp[exp_idx] == 'MAT_EXP':
        exp.materialExplosionFactor = factors[exp_idx]
    elif cell_exp[exp_idx] == 'ALL_CELL_EXP':
        exp.explodeAllCells     = 1
        exp.cellExplosionFactor = factors[exp_idx]
  
 
    #
    # Retrieve the material name, and then add this 
    # explosion to our main attributes. 
    #
    exp.material = mat_names[exp_idx]
    main_atts.AddExplosions(exp)
    
#
# Set our main attributes as the operator's atts, and
# draw our plot. 
#
SetOperatorOptions(main_atts)
DrawPlots()

#
# This section is creating views for the movie. Because this
# is not unique to the explode operator, I will not go over
# this section. If you are new to creating general movie scripts 
# in VisIt, there are several tutorials to help with this. 
#

#FIXME: action needed
#*******************************
# Create views here.
#*******************************

#
# Movie making magic. 
#
#FIXME: action needed
#*******************************
#
#num_views = 
#views = (v0, v1, ...)
#x = []
#for i in range(num_views):
#    x = x + [float(i)/float(num_views-1)]
#*******************************


#
# Decide on the number of steps/frames you want in creating your movie. 
# Also, keep track of the halfway point. 
#
#FIXME: action needed
#*******************************
#nsteps =
#half   = 
#*******************************


#
# Here is where we enact the explosions over time and
# create the frames for our movie. 
#
for i in range(nsteps):
    t = float(i) / float(nsteps - 1)
    c = EvalCubicSpline(t, x, views)
    SetView3D(c)
    
    #
    # Retrieve all of our explosions from main_atts. 
    # These are simply retrieved by index and remain
    # in the order they were added (first -> 0th idx). 
    #
    exp_list = []
    for mat in range(num_exp):
        exp_list.append(main_atts.GetExplosions(mat))

    #
    # Now that we have a list of our explosions, 
    # clear them from the main_atts. We will
    # alter our explosions and re-add them all. 
    #
    main_atts.ClearExplosions()

    for exp_idx in range(len(exp_list)):
        exp = exp_list[exp_idx]

        #        
        # If we are less than halfway, increase each explosion's
        # factor by the amount in 'change'. If we are at or beyond
        # the halfway point, subtract that amount from our factors. 
        #
        if i < half:
            factors[exp_idx] += change[exp_idx]
        else:
            factors[exp_idx] -= change[exp_idx]
       
        if cell_exp[exp_idx] == 'MAT_CELL_EXP':
            exp.materialExplosionFactor = 0
            exp.explodeMaterialCells    = 1
            exp.cellExplosionFactor     = factors[exp_idx]
        elif cell_exp[exp_idx] == 'MAT_EXP':
            exp.materialExplosionFactor = factors[exp_idx]
        elif cell_exp[exp_idx] == 'ALL_CELL_EXP':
            exp.explodeAllCells     = 1
            exp.cellExplosionFactor = factors[exp_idx]


        #
        # Add the explosions back to our main attributes. 
        #
        main_atts.AddExplosions(exp)

    SetOperatorOptions(main_atts)
    swatts.fileName = "explode_rect2_%04d.png"%i
    SetSaveWindowAttributes(swatts)
    SaveWindow()

#
# Generate the movie!
#
input_pattern = "explode_rect2_%04d.png"
output_movie = "rect_exp.wmv"
encoding.encode(input_pattern,output_movie,fdup=4)

Example Scripts

The following scripts are directly based off of the tempate script above, and their corresponding example videos are located in the Example Movies section.

Box Explosion

##########################################################
# Author: Alister Maguire
# Date: Tue Mar 13 10:59:22 PDT 2018
#
# This script is meant to act as a guide for making movies
# with the Explode Operator. This guide does not go over 
# details specific to making movies in general. For 
# information about making movies in general, there are 
# several guides available through visitusers.org
#
##########################################################

from visit_utils import *

OpenDatabase("rect3d.silo")

#
# Remove the window annotations
#
annotationAtts = AnnotationAttributes()
annotationAtts.axes2D.visible = 0
annotationAtts.axes3D.visible = 0
annotationAtts.axes3D.triadFlag = 0
annotationAtts.axes3D.bboxFlag = 0
annotationAtts.userInfoFlag = 0
annotationAtts.databaseInfoFlag = 0
annotationAtts.legendInfoFlag = 0
SetAnnotationAttributes(annotationAtts)

#
# Create the attributes for saving windows
#
swatts = SaveWindowAttributes()
swatts.family = 0
swatts.format = swatts.PNG 
swatts.width = 1024 
swatts.height = 1024

#
# Add a plot and change whatever plot attributes you'd like to change. 
# In this case, I'm using a filled boundary plot.
#
AddPlot("FilledBoundary", "mat1")

#
# Add the explode operator, and retrieve an instance of 
# the Explode Attributes. This instance of the attributes
# will be the operator's primary source for exposions. As
# you will see, all future instances of Explode Attributes 
# will be added to this one. 
#
AddOperator("Explode")
main_atts = ExplodeAttributes()
num_exp   = 8 # number of explosions desired

#
# In this case, all the materials of this dataset have
# generic, numerical names. 
#
mat_names =  []
for i in range(num_exp):
    mat_names.append(str(i))


#
# The next section is dedicated to creating 'helper
# lists', which just help in creating explosions later.
# All of these lists are of size num_exp, and the ith
# index corresponds to the ith explosion. For instance,
# helper_list[0] would retrieve data for the first
# explosion, and helper_list[13] would retrieve data
# for the 14th explosion.  
#

#
# Here, I'm creating a list of explosion factors and 
# a list of 'changes'. The changes are the amount of 
# change that is applied to the factor each iteration. 
# This results in objects being gradually exploded away 
# from (or towards) their origin over time.
#
factors = [.01]*num_exp
change  = [.08, .07, .06, .05, .04, .03, .02, .01]

#
# Minimizing the degrees of change. This is just a convience.
#
for i in range(len(change)):
    change[i] = change[i] / 3.0


#
# In this video, all of our explosions are originating from a
# single plane. 
#
z_plane_mid = ((0.499999, 0.499999, 0.499999), (0, 0, 1))

planes = [z_plane_mid, z_plane_mid, z_plane_mid, z_plane_mid,  
          z_plane_mid, z_plane_mid, z_plane_mid, z_plane_mid, 
          z_plane_mid, z_plane_mid, z_plane_mid, z_plane_mid,
          z_plane_mid, z_plane_mid]


#
# Create a list of explosion types. 
#
exp_type = [main_atts.Plane]*num_exp

#
# Here's where I create the actual explosions. In this case, 
# I'm exploding every material exactly once. 
#
for exp_idx in range(num_exp):

    #
    # Retrieve a new instance of Explode Attributes and 
    # set its type. 
    #
    exp = ExplodeAttributes()
    exp.explosionType = exp_type[exp_idx]

    exp.planePoint = planes[exp_idx][0]
    exp.planeNorm  = planes[exp_idx][1]

    exp.materialExplosionFactor = 0
    exp.explodeMaterialCells    = 1
    exp.cellExplosionFactor     = factors[exp_idx]

    #
    # Retrieve the material name, and then add this 
    # explosion to our main attributes. 
    #
    exp.material = mat_names[exp_idx]
    main_atts.AddExplosions(exp)
    
#
# Set our main attributes as the operator's atts, and
# draw our plot. 
#
SetOperatorOptions(main_atts)
DrawPlots()

#
# This section is creating views for the movie. Because this
# is not unique to the explode operator, I will not go over
# this section. If you are new to creating general movie scripts 
# in VisIt, there are several tutorials to help with this. 
#

# Begin spontaneous state
v0 = View3DAttributes()
v0.viewNormal = (0.279152, 0.124992, 0.952077)
v0.focus = (0.5, 0.5, 0.5)
v0.viewUp = (-0.0202153, 0.992037, -0.124311)
v0.viewAngle = 30
v0.parallelScale = 3.57071
v0.nearPlane = -7.14143
v0.farPlane = 7.14143
v0.imagePan = (0, 0)
v0.imageZoom = 1
v0.perspective = 1
v0.eyeAngle = 2
v0.centerOfRotationSet = 0
v0.centerOfRotation = (0.5, 0.5, 0.5)
v0.axis3DScaleFlag = 0
v0.axis3DScales = (1, 1, 1)
v0.shear = (0, 0, 1)
v0.windowValid = 1
SetView3D(v0)
# End spontaneous state

# Begin spontaneous state
v1 = View3DAttributes()
v1.viewNormal = (0.548049, 0.198826, 0.812472)
v1.focus = (0.5, 0.5, 0.5)
v1.viewUp = (-0.0889465, 0.979683, -0.179747)
v1.viewAngle = 30
v1.parallelScale = 3.57071
v1.nearPlane = -7.14143
v1.farPlane = 7.14143
v1.imagePan = (0, 0)
v1.imageZoom = 1
v1.perspective = 1
v1.eyeAngle = 2
v1.centerOfRotationSet = 0
v1.centerOfRotation = (0.5, 0.5, 0.5)
v1.axis3DScaleFlag = 0
v1.axis3DScales = (1, 1, 1)
v1.shear = (0, 0, 1)
v1.windowValid = 1
SetView3D(v1)
# End spontaneous state

# Begin spontaneous state
v2 = View3DAttributes()
v2.viewNormal = (0.705145, 0.500195, 0.502569)
v2.focus = (0.5, 0.5, 0.5)
v2.viewUp = (-0.443191, 0.864182, -0.238268)
v2.viewAngle = 30
v2.parallelScale = 3.57071
v2.nearPlane = -7.14143
v2.farPlane = 7.14143
v2.imagePan = (0, 0)
v2.imageZoom = 1
v2.perspective = 1
v2.eyeAngle = 2
v2.centerOfRotationSet = 0
v2.centerOfRotation = (0.5, 0.5, 0.5)
v2.axis3DScaleFlag = 0
v2.axis3DScales = (1, 1, 1)
v2.shear = (0, 0, 1)
v2.windowValid = 1
SetView3D(v2)
# End spontaneous state

# Begin spontaneous state
v3 = View3DAttributes()
v3.viewNormal = (0.605409, 0.698378, -0.381771)
v3.focus = (0.5, 0.5, 0.5)
v3.viewUp = (-0.702269, 0.694449, 0.156711)
v3.viewAngle = 30
v3.parallelScale = 3.57071
v3.nearPlane = -7.14143
v3.farPlane = 7.14143
v3.imagePan = (0, 0)
v3.imageZoom = 1
v3.perspective = 1
v3.eyeAngle = 2
v3.centerOfRotationSet = 0
v3.centerOfRotation = (0.5, 0.5, 0.5)
v3.axis3DScaleFlag = 0
v3.axis3DScales = (1, 1, 1)
v3.shear = (0, 0, 1)
v3.windowValid = 1
SetView3D(v3)
# End spontaneous state

# Begin spontaneous state
v4 = View3DAttributes()
v4.viewNormal = (0.258694, 0.569737, -0.780049)
v4.focus = (0.5, 0.5, 0.5)
v4.viewUp = (-0.389806, 0.800439, 0.455356)
v4.viewAngle = 30
v4.parallelScale = 3.57071
v4.nearPlane = -7.14143
v4.farPlane = 7.14143
v4.imagePan = (0, 0)
v4.imageZoom = 1
v4.perspective = 1
v4.eyeAngle = 2
v4.centerOfRotationSet = 0
v4.centerOfRotation = (0.5, 0.5, 0.5)
v4.axis3DScaleFlag = 0
v4.axis3DScales = (1, 1, 1)
v4.shear = (0, 0, 1)
v4.windowValid = 1
SetView3D(v4)
# End spontaneous state

# Begin spontaneous state
v5 = View3DAttributes()
v5.viewNormal = (-0.142344, 0.630536, -0.762996)
v5.focus = (0.5, 0.5, 0.5)
v5.viewUp = (0.746076, 0.574916, 0.33592)
v5.viewAngle = 30
v5.parallelScale = 3.57071
v5.nearPlane = -7.14143
v5.farPlane = 7.14143
v5.imagePan = (0, 0)
v5.imageZoom = 1
v5.perspective = 1
v5.eyeAngle = 2
v5.centerOfRotationSet = 0
v5.centerOfRotation = (0.5, 0.5, 0.5)
v5.axis3DScaleFlag = 0
v5.axis3DScales = (1, 1, 1)
v5.shear = (0, 0, 1)
v5.windowValid = 1
SetView3D(v5)
# End spontaneous state

# Begin spontaneous state
v6 = View3DAttributes()
v6.viewNormal = (0.184043, 0.810065, -0.556708)
v6.focus = (0.5, 0.5, 0.5)
v6.viewUp = (0.982613, -0.137528, 0.124727)
v6.viewAngle = 30
v6.parallelScale = 3.57071
v6.nearPlane = -7.14143
v6.farPlane = 7.14143
v6.imagePan = (0, 0)
v6.imageZoom = 1
v6.perspective = 1
v6.eyeAngle = 2
v6.centerOfRotationSet = 0
v6.centerOfRotation = (0.5, 0.5, 0.5)
v6.axis3DScaleFlag = 0
v6.axis3DScales = (1, 1, 1)
v6.shear = (0, 0, 1)
v6.windowValid = 1
SetView3D(v6)
# End spontaneous state




views = (v0, v1, v2, v3, v4, v5, v6)
x = []
for i in range(7):
    x = x + [float(i)/float(6)]

#
# I want 250 steps in total, and I want the explosions
# to start retracting at the halfway point. 
#
nsteps = 250
half   = 125

for i in range(nsteps):
    t = float(i) / float(nsteps - 1)
    c = EvalCubicSpline(t, x, views)
    SetView3D(c)
    
    #
    # Retrieve all of our explosions from main_atts. 
    # These are simply retrieved by index and remain
    # in the order they were added (first -> 0th idx). 
    #
    exp_list = []
    for mat in range(num_exp):
        exp_list.append(main_atts.GetExplosions(mat))

    #
    # Now that we have a list of our explosions, 
    # we should clear them from the main_atts. We will
    # alter our explosions and re-add them all. 
    #
    main_atts.ClearExplosions()

    for exp_idx in range(len(exp_list)):

        exp = exp_list[exp_idx]

        #        
        # If we are less than halfway, increase each explosion's
        # factor by the amount in 'change'. If we are at or beyond
        # the halfway point, subtract that amount from our factors. 
        #
        if i < 125:
            factors[exp_idx] += change[exp_idx]
        else:
            factors[exp_idx] -= change[exp_idx]
       
        exp.materialExplosionFactor = 0
        exp.explodeMaterialCells    = 1
        exp.cellExplosionFactor     = factors[exp_idx]

        #
        # Add the explosions back to our main attributes. 
        #
        main_atts.AddExplosions(exp)

    SetOperatorOptions(main_atts)
    swatts.fileName = "explode_rect2_%04d.png"%i
    SetSaveWindowAttributes(swatts)
    SaveWindow()

input_pattern = "explode_rect2_%04d.png"
output_movie = "rect_exp.wmv"
encoding.encode(input_pattern,output_movie,fdup=4)

Clock Explosion

##########################################################
# Author: Alister Maguire
# Date: Tue Mar 13 10:59:22 PDT 2018
#
# This script is meant to act as a guide for making movies
# with the Explode Operator. This guide does not go over 
# details specific to making movies in general. For 
# information about making movies in general, there are 
# several guides available through visitusers.org
#
##########################################################

from visit_utils import *

OpenDatabase("CLOCK2.vtk")

#
# Remove the window annotations
#
annotationAtts = AnnotationAttributes()
annotationAtts.axes2D.visible = 0
annotationAtts.axes3D.visible = 0
annotationAtts.axes3D.triadFlag = 0
annotationAtts.axes3D.bboxFlag = 0
annotationAtts.userInfoFlag = 0
annotationAtts.databaseInfoFlag = 0
annotationAtts.legendInfoFlag = 0
SetAnnotationAttributes(annotationAtts)

#
# Create the attributes for saving windows
#
swatts = SaveWindowAttributes()
swatts.family = 0
swatts.format = swatts.PNG 
swatts.width = 1024 
swatts.height = 1024

#
# Add a plot and change whatever plot attributes you'd like to change. 
# In this case, I'm using a filled boundary plot and altering the 
# default material colors. 
#
AddPlot("FilledBoundary", "materials")
FilledBoundaryAtts = FilledBoundaryAttributes()
FilledBoundaryAtts.colorType = FilledBoundaryAtts.ColorByMultipleColors 
FilledBoundaryAtts.colorTableName = "Default"
FilledBoundaryAtts.invertColorTable = 0
FilledBoundaryAtts.legendFlag = 1
FilledBoundaryAtts.lineStyle = FilledBoundaryAtts.SOLID  
FilledBoundaryAtts.lineWidth = 0
FilledBoundaryAtts.singleColor = (0, 0, 0, 255)
FilledBoundaryAtts.SetMultiColor(0, (0, 0, 83, 3))
FilledBoundaryAtts.SetMultiColor(1, (0, 0, 103, 255))
FilledBoundaryAtts.SetMultiColor(2, (3, 57, 124, 255))
FilledBoundaryAtts.SetMultiColor(3, (3, 87, 117, 255))
FilledBoundaryAtts.SetMultiColor(4, (3, 101, 134, 255))
FilledBoundaryAtts.SetMultiColor(5, (1, 131, 143, 255))
FilledBoundaryAtts.SetMultiColor(6, (1, 143, 131, 10))
FilledBoundaryAtts.SetMultiColor(7, (231, 231, 2, 255))
FilledBoundaryAtts.SetMultiColor(8, (231, 231, 2, 255))
FilledBoundaryAtts.SetMultiColor(9, (87, 167, 138, 255))
FilledBoundaryAtts.SetMultiColor(10, (231, 231, 2, 255))
FilledBoundaryAtts.SetMultiColor(11, (231, 231, 2, 255))
FilledBoundaryAtts.SetMultiColor(12, (231, 231, 2, 255))
FilledBoundaryAtts.SetMultiColor(13, (231, 231, 2, 255))
FilledBoundaryAtts.boundaryNames = ("0", "1", "2", "3", "4", "5", "6", "7", 
                                    "8", "9", "10", "11", "12", "13")
FilledBoundaryAtts.opacity = 1
FilledBoundaryAtts.wireframe = 0
FilledBoundaryAtts.drawInternal = 0
FilledBoundaryAtts.smoothingLevel = 0
FilledBoundaryAtts.cleanZonesOnly = 0
FilledBoundaryAtts.mixedColor = (255, 255, 255, 255)
FilledBoundaryAtts.pointSize = 0.05
FilledBoundaryAtts.pointType = FilledBoundaryAtts.Point 
FilledBoundaryAtts.pointSizeVarEnabled = 0
FilledBoundaryAtts.pointSizeVar = "default"
FilledBoundaryAtts.pointSizePixels = 2
SetPlotOptions(FilledBoundaryAtts)


#
# Add the explode operator, and retrieve an instance of 
# the Explode Attributes. This instance of the attributes
# will be the operator's primary source for exposions. As
# you will see, all future instances of Explode Attributes 
# will be added to this one. 
#
AddOperator("Explode")
main_atts = ExplodeAttributes()
num_exp   = 14 # number of explosions desired

#
# The next section is dedicated to creating 'helper
# lists', which just help in creating explosions later.
# All of these lists are of size num_exp, and the ith
# index corresponds to the ith explosion. For instance,
# helper_list[0] would retrieve data for the first
# explosion, and helper_list[13] would retrieve data
# for the 14th explosion.  
#

#
# In this case, all the materials of this dataset have
# generic, numerical names. 
#
mat_names =  []
for i in range(num_exp):
    mat_names.append(str(i))

#
# Here, I'm creating a list of explosion factors and 
# a list of 'changes'. The changes are the amount of 
# change that is applied to the factor each iteration. 
# This results in objects being gradually exploded away 
# from (or towards) their origin over time.
#
factors   =  [.01]*num_exp
change    =  [.04, .05, .04, .04, .03, .01, .022, .04,
              .035, .05, .05, .03, .045, .02]   

#
# Minimizing the degrees of change. This is just a convience.
#
for i in range(len(change)):
    change[i] = change[i] / 3.0

#
# In this video, all of our explosions are originating from 
# planes that intersect the midpoint of the dataset. For convenience, 
# I've created three lists of tuples (x_plane_mid, y_plane_mid, 
# z_plane_mid) which hold the midplane for their respective coordinate
# in the first position and the normal for that plane in the second 
# position. I then create a list of planes which correspond to 
# individual explosions. 
#
x_plane_mid = [(54.8, 0, 0), (1, 0, 0)]
y_plane_mid = [(0, 60, 0), (0, 1, 0)]
z_plane_mid = [(0, 0, 22), (0, 0, 1)]

planes = [z_plane_mid, z_plane_mid, z_plane_mid, y_plane_mid,  
          x_plane_mid, z_plane_mid, z_plane_mid, y_plane_mid, 
          y_plane_mid, z_plane_mid, y_plane_mid, y_plane_mid,
          y_plane_mid, y_plane_mid]

#
# Create a list of explosion types. 
#
exp_type = [main_atts.Plane]*num_exp


#
# All but one of my explosions will be exploding materials. 
# The 5th material in my list will have its cells exploded. 
#
cell_exp    = ['MAT_EXP'] * num_exp
cell_exp[4] = 'MAT_CELL_EXP' 

#
# Here's where I create the actual explosions. In this case, 
# I'm exploding every material exactly once. 
#
#for mat in range(num_exp):
for exp_idx in range(num_exp):
    #
    # Retrieve a new instance of Explode Attributes and 
    # set its type. 
    #
    exp = ExplodeAttributes()
    exp.explosionType = exp_type[exp_idx]

    exp.planePoint = planes[exp_idx][0]
    exp.planeNorm  = planes[exp_idx][1]

    if cell_exp[exp_idx] == 'MAT_CELL_EXP':
        exp.materialExplosionFactor = 0
        exp.explodeMaterialCells    = 1
        exp.cellExplosionFactor     = factors[exp_idx]
    elif cell_exp[exp_idx] == 'MAT_EXP':
        exp.materialExplosionFactor = factors[exp_idx]

    #
    # Retrieve the material name, and then add this 
    # explosion to our main attributes. 
    #
    exp.material = mat_names[exp_idx]
    main_atts.AddExplosions(exp)
    
#
# Set our main attributes as the operator's atts, and
# draw our plot. 
#
SetOperatorOptions(main_atts)
DrawPlots()

#
# This section is creating views for the movie. Because this
# is not unique to the explode operator, I will not go over
# this section. If you are new to creating general movie scripts 
# in VisIt, there are several tutorials to help with this. 
#
v0 = View3DAttributes()
v0.viewNormal = (-0.00218947, -0.00231618, 0.999995)
v0.focus = (54.8305, 67.2785, 24.5655)
v0.viewUp = (2.36974e-06, 0.999997, 0.00231619)
v0.viewAngle = 30
v0.parallelScale = 77.3777
v0.nearPlane = -154.755
v0.farPlane = 154.755
v0.imagePan = (0, 0)
v0.imageZoom = 1
v0.perspective = 1
v0.eyeAngle = 2
v0.centerOfRotationSet = 0
v0.centerOfRotation = (54.8305, 67.2785, 24.5655)
v0.axis3DScaleFlag = 0
v0.axis3DScales = (1, 1, 1)
v0.shear = (0, 0, 1)
v0.windowValid = 1

v1 = View3DAttributes()
v1.viewNormal = (0.342491, 0.0409873, 0.938627)
v1.focus = (54.8305, 67.2785, 24.5655)
v1.viewUp = (-0.00471964, 0.99911, -0.0419063)
v1.viewAngle = 30
v1.parallelScale = 77.3777
v1.nearPlane = -154.755
v1.farPlane = 154.755
v1.imagePan = (0, 0)
v1.imageZoom = 0.466507
v1.perspective = 1
v1.eyeAngle = 2
v1.centerOfRotationSet = 0
v1.centerOfRotation = (54.8305, 67.2785, 24.5655)
v1.axis3DScaleFlag = 0
v1.axis3DScales = (1, 1, 1)
v1.shear = (0, 0, 1)
v1.windowValid = 1

v2 = View3DAttributes()
v2.viewNormal = (0.999206, -0.0371915, 0.0143127)
v2.focus = (54.8305, 59.187, 23.4759)
v2.viewUp = (0.0372007, 0.999308, -0.000374587)
v2.viewAngle = 30
v2.parallelScale = 426.661
v2.nearPlane = -853.323
v2.farPlane = 853.323
v2.imagePan = (0, 0)
v2.imageZoom = 1
v2.perspective = 1
v2.eyeAngle = 2
v2.centerOfRotationSet = 0
v2.centerOfRotation = (54.8305, 59.187, 23.4759)
v2.axis3DScaleFlag = 0
v2.axis3DScales = (1, 1, 1)
v2.shear = (0, 0, 1)
v2.windowValid = 1

v3 = View3DAttributes()
v3.viewNormal = (0.00690994, 0.0204159, -0.999768)
v3.focus = (54.8305, 59.187, 23.4759)
v3.viewUp = (-0.00349062, 0.999786, 0.0203921)
v3.viewAngle = 30
v3.parallelScale = 426.661
v3.nearPlane = -853.323
v3.farPlane = 853.323
v3.imagePan = (0, 0)
v3.imageZoom = 1
v3.perspective = 1
v3.eyeAngle = 2
v3.centerOfRotationSet = 0
v3.centerOfRotation = (54.8305, 59.187, 23.4759)
v3.axis3DScaleFlag = 0
v3.axis3DScales = (1, 1, 1)
v3.shear = (0, 0, 1)
v3.windowValid = 1

v4 = View3DAttributes()
v4.viewNormal = (-0.998344, 0.0573615, 0.00425611)
v4.focus = (54.8305, 59.187, 23.4759)
v4.viewUp = (0.0573239, 0.99832, -0.00848328)
v4.viewAngle = 30
v4.parallelScale = 426.661
v4.nearPlane = -853.323
v4.farPlane = 853.323
v4.imagePan = (0, 0)
v4.imageZoom = 1.4641
v4.perspective = 1
v4.eyeAngle = 2
v4.centerOfRotationSet = 0
v4.centerOfRotation = (54.8305, 59.187, 23.4759)
v4.axis3DScaleFlag = 0
v4.axis3DScales = (1, 1, 1)
v4.shear = (0, 0, 1)
v4.windowValid = 1

v5 = View3DAttributes()
v5.viewNormal = (-0.752243, 0.0439464, 0.657419)
v5.focus = (54.8305, 59.187, 23.4759)
v5.viewUp = (0.0396421, 0.998984, -0.021419)
v5.viewAngle = 30
v5.parallelScale = 426.661
v5.nearPlane = -853.323
v5.farPlane = 853.323
v5.imagePan = (0, 0)
v5.imageZoom = 1.77156
v5.perspective = 1
v5.eyeAngle = 2
v5.centerOfRotationSet = 0
v5.centerOfRotation = (54.8305, 59.187, 23.4759)
v5.axis3DScaleFlag = 0
v5.axis3DScales = (1, 1, 1)
v5.shear = (0, 0, 1)
v5.windowValid = 1

v6 = View3DAttributes()
v6.viewNormal = (-0.00218947, -0.00231618, 0.999995)
v6.focus = (54.8305, 67.2785, 24.5655)
v6.viewUp = (2.36974e-06, 0.999997, 0.00231619)
v6.viewAngle = 30
v6.parallelScale = 77.3777
v6.nearPlane = -154.755
v6.farPlane = 154.755
v6.imagePan = (0, 0)
v6.imageZoom = 1
v6.perspective = 1
v6.eyeAngle = 2
v6.centerOfRotationSet = 0
v6.centerOfRotation = (54.8305, 67.2785, 24.5655)
v6.axis3DScaleFlag = 0
v6.axis3DScales = (1, 1, 1)
v6.shear = (0, 0, 1)
v6.windowValid = 1

views = (v0, v1, v2, v3, v4, v5, v6)
x = []
for i in range(7):
    x = x + [float(i)/float(6)]

#
# I want 250 steps in total, and I want the explosions
# to start retracting at the halfway point. 
#
nsteps = 250
half   = 125

for i in range(nsteps):
    t = float(i) / float(nsteps - 1)
    c = EvalCubicSpline(t, x, views)
    SetView3D(c)
    
    #
    # Retrieve all of our explosions from main_atts. 
    # These are simply retrieved by index and remain
    # in the order they were added (first -> 0th idx). 
    #
    exp_list = []
    for mat in range(num_exp):
        exp_list.append(main_atts.GetExplosions(mat))

    #
    # Now that we have a list of our explosions, 
    # we should clear them from the main_atts. We will
    # alter our explosions and re-add them all. 
    #
    main_atts.ClearExplosions()

    for exp_idx in range(len(exp_list)):
        exp = exp_list[exp_idx]

        #        
        # If we are less than halfway, increase each explosion's
        # factor by the amount in 'change'. If we are at or beyond
        # the halfway point, subtract that amount from our factors. 
        #
        if i < 125:
            factors[exp_idx] += change[exp_idx]
        else:
            factors[exp_idx] -= change[exp_idx]
       
        if cell_exp[exp_idx] == 'MAT_CELL_EXP':
            exp.materialExplosionFactor = 0
            exp.explodeMaterialCells    = 1
            exp.cellExplosionFactor     = factors[exp_idx]
        elif cell_exp[exp_idx] == 'MAT_EXP':
            exp.materialExplosionFactor = factors[exp_idx]

        #
        # Add the explosions back to our main attributes. 
        #
        main_atts.AddExplosions(exp)

    SetOperatorOptions(main_atts)
    swatts.fileName = "explode_clock_%04d.png"%i
    SetSaveWindowAttributes(swatts)
    SaveWindow()

input_pattern = "explode_clock_%04d.png"
output_movie = "movie.wmv"
encoding.encode(input_pattern,output_movie,fdup=4)