Example #1
0
        def createComposite(self):
            try:
                simple.LoadDistributedPlugin("RGBZView", ns=globals())
                self.analysis.register_analysis(
                    "composite", "Composite rendering",
                    "Performing composite on contour",
                    '{time}/{theta}/{phi}/{filename}',
                    cinema.CompositeImageExporter.get_data_type())
                fng = self.analysis.get_file_name_generator("composite")

                # Create pipeline to compose
                color_type = [('POINT_DATA', "velocity")]
                luts = {"velocity": self.lut}
                filters = [input]
                filters_description = [{'name': 'catalyst'}]
                color_by = [color_type]

                # Data exploration ------------------------------------------------------------
                camera_handler = cinema.ThreeSixtyCameraHandler(
                    fng, None, [float(r) for r in range(0, 360, 72)],
                    [float(r) for r in range(-60, 61, 45)],
                    self.center_of_rotation, self.rotation_axis, self.distance)
                exporter = cinema.CompositeImageExporter(
                    fng, filters, color_by, luts, camera_handler, [400, 400],
                    filters_description, 0, 0)
                exporter.set_analysis(self.analysis)
                self.exporters.append(exporter)
            except:
                print "Skip RGBZView exporter"
Example #2
0
def doProcessing(outputDir, timesteps):
    # -----------------------------------------------------------------------------
    # Configuration
    # -----------------------------------------------------------------------------

    data_to_process = {
        "T": {
            "scalarRange": [178, 312],
            "contours": [265, 275, 285, 295]
        }
    }

    #resolution = 500
    resolution = 500
    #phis = [ 90, 180 ]
    #thetas = [ 0.0 ]
    phis = [float(r) for r in range(0, 360, 20)]
    thetas = [-80.0, -60.0, -30.0, 0.0, 30.0, 60.0, 80.0]
    distance = 450
    rotation_axis = [0.0, 0.0, 1.0]
    center_of_rotation = [0.0, 0.0, 0.0]

    # -----------------------------------------------------------------------------
    # Input data definition
    # -----------------------------------------------------------------------------

    #path_root = '/Volumes/OLeary'
    path_root = '/media/scott/CINEMA FAT'

    data_base_path = os.path.join(path_root, 'cam5')
    earth_core_path = os.path.join(data_base_path, 'earth-high.vtk')

    #output_working_dir = os.path.join(path_root, 'Output/MPAS/web-generated/mpas-composite')
    #output_working_dir = '/home/scott/Documents/cinemaDemo/simpleCinemaWebGL/cam5/contour-webgl-light'
    output_working_dir = os.path.join(outputDir, 'contour-webgl-light')

    earth_file = os.path.join(data_base_path, 'earth.vtk')
    file_pattern = os.path.join(data_base_path, 'cam5earth_%d.vtk')
    #file_times = range(0, 13, 1)
    #file_times = [ 6 ]
    file_times = timesteps
    cam5_filenames = [(file_pattern % int(time)) for time in file_times]

    # -----------------------------------------------------------------------------
    # Pipeline definition
    # -----------------------------------------------------------------------------

    cam5earth = LegacyVTKReader(FileNames=cam5_filenames)

    earthvtk = LegacyVTKReader(FileNames=[earth_file])
    extract_globe_surface = ExtractSurface(Input=earthvtk)
    surface_normals = GenerateSurfaceNormals(Input=extract_globe_surface)

    # Generate iso contours
    contours = {}
    for field in data_to_process:
        contours[field] = []
        for isoValue in data_to_process[field]['contours']:
            contours[field].append(
                Contour(Input=cam5earth,
                        PointMergeMethod="Uniform Binning",
                        ContourBy=field,
                        Isosurfaces=[isoValue],
                        ComputeScalars=1))

    # -----------------------------------------------------------------------------
    # Output configuration
    # -----------------------------------------------------------------------------

    title = "Visualizations from Cam5 Data"
    description = """
                  Atmospheric Simulations
                  """

    analysis = wx.AnalysisManager(output_working_dir,
                                  title,
                                  description,
                                  author="Patrick O'Leary",
                                  code_name="cam5",
                                  code_version="N/A",
                                  cores=1)

    # -----------------------------------------------------------------------------
    # Pre-calculate ranges
    # -----------------------------------------------------------------------------

    globalRanges = {
        'T': [10000000, -10000000],
        'U': [10000000, -10000000],
        'V': [10000000, -10000000],
        'magnitude': [10000000, -10000000]
    }

    print 'Calculating data array ranges over time'
    for time in file_times:
        t = int(time)
        print '  timestep ', t
        cam5earth.UpdatePipeline(t)
        pdi = cam5earth.GetPointDataInformation()

        for key in globalRanges.keys():
            globalRanges[key] = updateGlobalRange(
                pdi.GetArray(key).GetRange(), globalRanges[key])

    print 'Discovered global ranges:'
    print globalRanges

    # -----------------------------------------------------------------------------
    # Composite generator
    # -----------------------------------------------------------------------------

    id = 'contours-lit'
    title = 'Lit 3D contours composite'
    description = '3D contour of temperature'
    analysis.register_analysis(id, title, description,
                               '{time}/{theta}/{phi}/{filename}',
                               wx.CompositeImageExporter.get_data_type())
    fng = analysis.get_file_name_generator(id)

    camera_handler = wx.ThreeSixtyCameraHandler(fng, None, phis, thetas,
                                                center_of_rotation,
                                                rotation_axis, distance)

    iso_color_array = [('VALUE', 'T'), ('VALUE', 'U'), ('VALUE', 'V'),
                       ('VALUE', 'magnitude'), ('VALUE', 'nX'),
                       ('VALUE', 'nY'), ('VALUE', 'nZ')]

    luts = {
        "T": ["point", "T", 0, globalRanges['T']],
        "U": ["point", "U", 0, globalRanges['U']],
        "V": ["point", "V", 0, globalRanges['V']],
        "magnitude": ["point", "magnitude", 0, globalRanges['magnitude']],
        "bottomDepth": ["point", "bottomDepth", 0, [-10277.0, 7170.0]],
        'nX': ['point', 'Normals', 0, (-1, 1)],
        'nY': ['point', 'Normals', 1, (-1, 1)],
        'nZ': ['point', 'Normals', 2, (-1, 1)]
    }

    composite_list = [surface_normals]
    composite_description = [{'name': 'Earth core'}]
    colors = [[('VALUE', 'bottomDepth'), ('VALUE', 'nX'), ('VALUE', 'nY'),
               ('VALUE', 'nZ')]]

    for field in contours:
        for iso in contours[field]:
            composite_description.append({
                'name':
                field[0] + "=" + str(iso.Isosurfaces[0]),
                'parent':
                "Contour by %s" % field
            })
            composite_list.append(iso)
            colors.append(iso_color_array)

    exporter = wx.CompositeImageExporter(fng,
                                         composite_list,
                                         colors,
                                         luts,
                                         camera_handler,
                                         [resolution, resolution],
                                         composite_description,
                                         format='png')  #, 0, 0)

    # Customize some view properties
    exporter.view.Background = [1.0, 1.0, 1.0]
    exporter.view.OrientationAxesVisibility = 0
    exporter.view.CenterAxesVisibility = 0

    exporter.set_analysis(analysis)

    # -----------------------------------------------------------------------------
    # Perform analysis
    # -----------------------------------------------------------------------------
    analysis.begin()

    for t in file_times:
        time = int(t)
        GetAnimationScene().TimeKeeper.Time = float(time)
        fng.update_active_arguments(time=time)
        print 'Generating images for timestep ', time
        exporter.UpdatePipeline(time)

    analysis.end()
Example #3
0
        filters.append(
            simple.Contour(Input=data_to_explore,
                           PointMergeMethod="Uniform Binning",
                           ContourBy=['POINTS', 'RTData'],
                           Isosurfaces=[iso_value],
                           ComputeScalars=1))
        color_by.append(color_type)
        filters_description.append({'name': 'iso=%s' % str(iso_value)})

    # Data exploration ------------------------------------------------------------
    camera_handler = cinema.ThreeSixtyCameraHandler(
        fng, None, [float(r) for r in range(0, 360, 72)],
        [float(r) for r in range(-60, 61, 45)], center_of_rotation,
        rotation_axis, distance)
    exporter = cinema.CompositeImageExporter(fng, filters, color_by, luts,
                                             camera_handler, [400, 400],
                                             filters_description, 0, 0)
    exporter.set_analysis(analysis)
    exporter.UpdatePipeline()

# === TODO ====================================================================
# ThreeSixtyImageStackExporter(file_name_generator, view_proxy, focal_point=[0.0,0.0,0.0], distance=100.0, rotation_axis=[0,0,1], angular_steps=[10,15])
# LineProber(file_name_generator, data_to_probe, points_series, number_of_points)
# DataProber(file_name_generator, data_to_probe, points_series, fields)
# TimeSerieDataProber(file_name_generator, data_to_probe, point_series, fields, time_to_write)
# === TODO ====================================================================

analysis.end()

# Print analysis info.json
analysisInfo = None
Example #4
0
# ---------------------------------------------------------------------------

title = "Composite test"
description = "Because test are important"
analysis = wx.AnalysisManager(output_dir, title, description)

id = 'composite'
title = '3D composite'
description = "contour set"
analysis.register_analysis(id, title, description, '{theta}/{phi}/{filename}',
                           wx.CompositeImageExporter.get_data_type())
fng = analysis.get_file_name_generator(id)

camera_handler = wx.ThreeSixtyCameraHandler(
    fng, None, [float(r) for r in range(0, 360, 45)],
    [float(r)
     for r in range(-60, 61, 45)], center_of_rotation, rotation_axis, distance)

# Data exploration ------------------------------------------------------------

exporter = wx.CompositeImageExporter(fng, filters, color_by, luts,
                                     camera_handler, [resolution, resolution],
                                     filters_description, 0, 0)
exporter.set_analysis(analysis)

# Processing ------------------------------------------------------------------

analysis.begin()
exporter.UpdatePipeline(0)
analysis.end()
Example #5
0
    'parent': 'Magnitude Thresholds'
}]
composite_colors = [[('SOLID_COLOR', [0.0, 0.0,
                                      0.0])], points_colors, points_colors,
                    points_colors, points_colors, points_colors, points_colors]

luts = {"magnitude": buildSpectralLUT('magnitude')}

# -----------------------------------------------------------------------------
# Data exploration
# -----------------------------------------------------------------------------

exporter = wx.CompositeImageExporter(fng,
                                     composite_list,
                                     composite_colors,
                                     luts,
                                     camera_handler, [resolution, resolution],
                                     composite_description,
                                     format='png')  # 0, 0)
exporter.set_analysis(analysis)

# -----------------------------------------------------------------------------
# Custumize view and some representations
# -----------------------------------------------------------------------------

exporter.view.Background = [1.0, 1.0, 1.0]
exporter.view.OrientationAxesVisibility = 0
exporter.view.CenterAxesVisibility = 0

calculatorRepr = Show(calculator1, exporter.view)
den1Repr = Show(den1, exporter.view)
Example #6
0
filters.append(cellToPoint)
color_by.append(color_type)
filters_description.append({'name': 'Computation Grid'})

# -----------------------------------------------------------------------------
# Rendering configuration
# -----------------------------------------------------------------------------

view_size = [1500, 750]
center_of_rotation = [0.0, 0.0, 0.0]

camera_handler = wx.ThreeSixtyCameraHandler(fng, None, [180], [0],
                                            center_of_rotation, [0, 1, 0], 6)

exporter = wx.CompositeImageExporter(fng, filters, color_by, luts,
                                     camera_handler, view_size,
                                     filters_description, 0, 0, 'png')

exporter.view.Background = [1.0, 1.0, 1.0]
exporter.view.OrientationAxesVisibility = 0
exporter.view.CenterAxesVisibility = 0

# Customize the look of the cells mask
readerRepr = Show(flat_reader, exporter.view)
readerRepr.Representation = 'Wireframe'
readerRepr.AmbientColor = [0.0, 0.0, 0.0]
readerRepr.ColorArrayName = [None, '']
readerRepr.ScalarOpacityUnitDistance = 0.30336485436433686

print "Begin processing"
def generateData(datasetPath, outputDir) :

    if not os.path.exists(outputDir):
        os.makedirs(outputDir)

    resolution = 500
    center_of_rotation = [0.0, 0.0, 0.0]
    rotation_axis = [0.0, 0.0, 1.0]
    distance = 45.0

    disk_out_refex2 = simple.ExodusIIReader(FileName=[datasetPath])
    disk_out_refex2.PointVariables = ['Temp', 'V', 'Pres', 'AsH3', 'GaMe3', 'CH4', 'H2']
    disk_out_refex2.NodeSetArrayStatus = []
    disk_out_refex2.SideSetArrayStatus = []
    disk_out_refex2.ElementBlocks = ['Unnamed block ID: 1 Type: HEX8']

    filters = []
    filters_description = []

    calculator1 = simple.Calculator(Input=disk_out_refex2)
    calculator1.ResultArrayName = 'Velocity'
    calculator1.Function = 'mag(V)'

    simple.UpdatePipeline()

    color_by = []

    #
    # COMPLAINT
    #
    # As a user of this system, I'd like not to have to specify that I need
    # 'nX', 'nY', and 'nZ' when I add a colorby of type "VALUE".  Instead,
    # I'd like it to figure out that I'm going to need normals for that kind
    # of rendering and add them for me.
    #
    color_type = [
        ('VALUE', "Velocity"),
        ('VALUE', "Pres"),
        ('VALUE', "Temp"),
        ('VALUE', "nX"),
        ('VALUE', "nY"),
        ('VALUE', "nZ")
    ]

    pdi = calculator1.GetPointDataInformation()

    #
    # COMPLAINT
    #
    # Ditto the above complaint here.
    #
    luts = {
        "Velocity": ["point", "Velocity", 0, pdi.GetArray("Velocity").GetRange()],
        "Pres": ["point", "Pres", 0, pdi.GetArray("Pres").GetRange()],
        "Temp": ["point", "Temp", 0, pdi.GetArray("Temp").GetRange()],
        "nX": ["point", "Normals", 0, (-1,1)],
        "nY": ["point", "Normals", 1, (-1,1)],
        "nZ": ["point", "Normals", 2, (-1,1)]
    }

    contour_values = [ 300.0, 600.0, 900.0 ]

    for iso_value in contour_values:
        contour = simple.Contour(
            Input=calculator1,
            PointMergeMethod="Uniform Binning",
            ContourBy = ['POINTS', 'Temp'],
            Isosurfaces = [iso_value],
            ComputeScalars = 1)

        # Add this isocontour to my list of filters
        filters.append( contour )
        color_by.append( color_type )
        filters_description.append( {'name': 'iso=%s' % str(iso_value), 'parent': "Contour by temperature"} )

    # create a new 'Stream Tracer'
    streamTracer1 = StreamTracer(Input=calculator1,
        SeedType='High Resolution Line Source')
    streamTracer1.Vectors = ['POINTS', 'V']
    streamTracer1.MaximumStreamlineLength = 20.15999984741211

    # init the 'High Resolution Line Source' selected for 'SeedType'
    streamTracer1.SeedType.Point1 = [-5.75, -5.75, -10.0]
    streamTracer1.SeedType.Point2 = [5.75, 5.75, 10.15999984741211]

    # create a new 'Tube'
    tube1 = Tube(Input=streamTracer1)
    tube1.Scalars = ['POINTS', 'Velocity']
    tube1.Vectors = ['POINTS', 'Normals']
    tube1.Radius = 0.10474160957336426

    #
    # COMPLAINT
    #
    # Here, because the "Normals" field of the tube filter is all funky
    # (directions seem to change at the seed points, when integration
    # proceeded in both directions), I actually needed to play around
    # with ParaView until I found a filter that would get me nice
    # looking normals.  Then, that filter didn't have a "Normals" field,
    # so I had to use a calculator to create it.  Not super nice from a
    # users perspective.
    #
    surfaceVectors1 = SurfaceVectors(Input=tube1)
    surfaceVectors1.SelectInputVectors = ['POINTS', 'TubeNormals']
    calculator2 = simple.Calculator(Input=surfaceVectors1)
    calculator2.ResultArrayName = 'Normals'
    calculator2.Function = 'TubeNormals'

    # Now add the stream tubes to the filters list
    filters.append(calculator2);
    color_by.append(color_type);
    filters_description.append({'name': 'Stream Tubes'})

    # create a new 'Clip'
    clip1 = Clip(Input=calculator1)
    clip1.ClipType = 'Plane'
    clip1.Value = 11.209410083552676
    clip1.InsideOut = 1

    # init the 'Plane' selected for 'ClipType'
    clip1.ClipType.Origin = [0.0, 0.0, 0.07999992370605469]
    clip1.ClipType.Normal = [0.7, 0.0, -0.4]

    #
    # COMPLAINT
    #
    # Here again, the output of the clip filter doesn't have a "Normals"
    # field on points, so I have to do some funky stuff to get what I
    # need.  It would be nice if this could be figured out for me
    # somehow.
    #
    extractSurface1 = ExtractSurface(Input=clip1)
    generateSurfaceNormals1 = GenerateSurfaceNormals(Input=extractSurface1)

    # Now add the first clip to the filters list
    filters.append(generateSurfaceNormals1);
    color_by.append(color_type);
    filters_description.append({'name': 'Clip One'})

    # create a new 'Clip'
    clip2 = Clip(Input=calculator1)
    clip2.ClipType = 'Plane'
    clip2.Value = 11.209410083552676
    clip2.InsideOut = 0

    # init the 'Plane' selected for 'ClipType'
    clip2.ClipType.Origin = [0.0, 0.0, 0.07999992370605469]
    clip2.ClipType.Normal = [0.7, 0.0, -0.4]

    #
    # COMPLAINT
    #
    # Ditto the above complaint here.
    #
    extractSurface2 = ExtractSurface(Input=clip2)
    generateSurfaceNormals2 = GenerateSurfaceNormals(Input=extractSurface2)

    # Now add the second clip to the filters list
    filters.append(generateSurfaceNormals2);
    color_by.append(color_type);
    filters_description.append({'name': 'Clip Two'})

    title = "Composite Dynamic Rendering - Disk Out Ref"
    description = "A sample dataset for dynamic rendering"
    analysis = wx.AnalysisManager(outputDir, title, description)

    id = 'composite'
    title = '3D composite'
    description = "contour set"
    analysis.register_analysis(id, title, description, '{theta}/{phi}/{filename}', wx.CompositeImageExporter.get_data_type()+"-light")
    fng = analysis.get_file_name_generator(id)

    camera_handler = wx.ThreeSixtyCameraHandler(
        fng,
        None,
        [ float(r) for r in range(0, 360, 30) ],
        [ float(r) for r in range(-60, 61, 60) ],
        center_of_rotation,
        rotation_axis,
        distance)

    exporter = wx.CompositeImageExporter(
        fng,
        filters,
        color_by,
        luts,
        camera_handler,
        [resolution,resolution],
        filters_description,
        0, 0, 'png')
    exporter.set_analysis(analysis)

    analysis.begin()
    exporter.UpdatePipeline(0)
    analysis.end()
Example #8
0
def doProcessing(inputDir, outputDir, sizeOption):

    # -----------------------------------------------------------------------------
    # Configuration
    # -----------------------------------------------------------------------------

    data_to_process = {
        "velMagnitude": {
            "scalarRange": [0.0, 6.0],
            "contours": [5, 7, 8],
        },
        "helicity": {
            "scalarRange": [-10000, 10000],
            "contours": [-5000, 5000]
        }
    }

    resolution = 500

    #phis = [ float(r) for r in range(0, 360, 90)]
    #thetas = [ 0.0, 55.0 ]
    phis = [float(r) for r in range(0, 360, 20)]
    thetas = [-80.0, -60.0, -30.0, 0.0, 30.0, 60.0, 80.0]

    centerOfRotation = {
        'shortFat':
        [0.03210659957176176, 0.03210659957176176, 2.08050000667572],
        'longFat':
        [0.1284263964244019, 0.1284263964244019, 2.2200000286102295],
        'longSkinny':
        [0.0064213199143523525, 0.0064213199143523525, 2.097312331199646]
    }

    rotation_axis = [0.0, 0.0, 1.0]

    distance = {'shortFat': 0.25, 'longFat': 1.16, 'longSkinny': 0.26}

    transformDims = {
        'shortFat': [5, 5, 1],
        'longFat': [20, 20, 1],
        'longSkinny': [1, 1, 1]
    }

    streamRes = {'shortFat': 30, 'longFat': 30, 'longSkinny': 30}

    streamLength = {'shortFat': 0.15, 'longFat': 1.5, 'longSkinny': 0.099899}

    tubeRadius = {'shortFat': 0.006, 'longFat': 0.03, 'longSkinny': 0.0025}

    seedLinePoints = {
        'shortFat': {
            'point1':
            [0.024308765645997044, 0.0047357203659974655, 2.083430515514084],
            'point2':
            [0.03917303628210819, 0.05936205001834852, 2.083314811121571]
        },
        'longFat': {
            'point1':
            [0.09957288686644243, 0.01765718560781814, 2.103601091698531],
            'point2':
            [0.16402243492110558, 0.24191479837166693, 2.090316776204166]
        },
        'longSkinny': {
            'point1': [
                0.004460199538914286, -1.9721305484628665e-05,
                2.0837601391639593
            ],
            'point2':
            [0.0084706015358675, 0.012500996772009757, 2.084043910210548]
        }
    }

    # -----------------------------------------------------------------------------
    # Input data definition
    # -----------------------------------------------------------------------------

    rodPaths = {
        'shortFat': 'rodShortest.vtk',
        'longFat': 'rodLong.vtk',
        'longSkinny': 'rodShorter.vtk'
    }

    rodPath = os.path.join(inputDir, rodPaths[sizeOption])
    blockFinsPath = os.path.join(inputDir, 'firstBlockFin.vtk')

    filePattern = {
        'shortFat': 'singlepin_shortest_%d.vtk',
        'longFat': 'singlepin_%d.vtk',
        'longSkinny': 'singlepin_clipped_%d.vtk'
    }

    fileTimes = range(13)  # all timesteps
    #fileTimes = [ 12 ]

    fileNames = [
        os.path.join(inputDir, (filePattern[sizeOption] % time))
        for time in fileTimes
    ]

    # -----------------------------------------------------------------------------
    # Pipeline definition
    # -----------------------------------------------------------------------------

    # Rod Core
    rodCore = LegacyVTKReader(FileNames=[rodPath])

    # create a new 'Transform'
    rodTransform = Transform(Input=rodCore)
    rodTransform.Transform = 'Transform'
    rodTransform.Transform.Scale = transformDims[sizeOption]

    # Phony calculator to give a "value" to render by
    rodSolidCalc = Calculator(Input=rodTransform)
    rodSolidCalc.ResultArrayName = 'rodSolid'
    rodSolidCalc.Function = '1'

    extractRodSurface = ExtractSurface(Input=rodSolidCalc)
    rodSurfaceNormals = GenerateSurfaceNormals(Input=extractRodSurface)

    # Block Fins
    blockFins = LegacyVTKReader(FileNames=[blockFinsPath])

    # create a new 'Transform'
    blockTransform = Transform(Input=blockFins)
    blockTransform.Transform = 'Transform'
    blockTransform.Transform.Scale = transformDims[sizeOption]

    # Another phony calculator
    blockSolidCalc = Calculator(Input=blockTransform)
    blockSolidCalc.ResultArrayName = 'blockSolid'
    blockSolidCalc.Function = '2'

    extractBlockSurface = ExtractSurface(Input=blockSolidCalc)
    blockFinsSurfaceNormals = GenerateSurfaceNormals(Input=extractBlockSurface)

    # Data pipeline
    reader = LegacyVTKReader(FileNames=fileNames)

    # create a new 'Transform'
    readerTransform = Transform(Input=reader)
    readerTransform.Transform = 'Transform'
    readerTransform.Transform.Scale = transformDims[sizeOption]

    # create a new 'Calculator'
    calculator1 = Calculator(Input=readerTransform)
    calculator1.ResultArrayName = 'velMagnitude'
    calculator1.Function = 'mag(vel)'

    # Generate iso contours
    contours = {}
    for field in data_to_process:
        contours[field] = []
        for isoValue in data_to_process[field]['contours']:
            contours[field].append(
                Contour(Input=calculator1,
                        PointMergeMethod="Uniform Binning",
                        ContourBy=field,
                        Isosurfaces=[isoValue],
                        ComputeScalars=1))

    # -----------------------------------------------------------------------------
    # Pre-calculate ranges
    # -----------------------------------------------------------------------------
    globalRanges = {
        'helicity': [10000000, -10000000],
        'vel': [10000000, -10000000],
        'vorticity': [10000000, -10000000]
    }

    for time in fileTimes:
        t = int(time)
        print '  timestep ', t
        reader.UpdatePipeline(t)
        pdi = reader.GetPointDataInformation()

        for key in globalRanges.keys():
            globalRanges[key] = updateGlobalRange(
                pdi.GetArray(key).GetRange(), globalRanges[key])

    print 'Discovered global ranges:'
    print globalRanges

    # -----------------------------------------------------------------------------
    # Composite generator
    # -----------------------------------------------------------------------------

    fng = wx.FileNameGenerator(outputDir, '{time}/{theta}/{phi}/{filename}')

    camera_handler = wx.ThreeSixtyCameraHandler(fng, None, phis, thetas,
                                                centerOfRotation[sizeOption],
                                                rotation_axis,
                                                distance[sizeOption])

    iso_color_array = [('VALUE', 'helicity'), ('VALUE', 'vel'),
                       ('VALUE', 'vorticity'), ('VALUE', 'nX'),
                       ('VALUE', 'nY'), ('VALUE', 'nZ')]

    luts = {
        "helicity": ["point", "helicity", 0, globalRanges['helicity']],
        "vel": ["point", "vel", -1, globalRanges['vel']],
        "vorticity": ["point", "vorticity", -1, globalRanges['vorticity']],
        "rodSolid": ["point", "rodSolid", 0, [1.0, 1.0]],
        "blockSolid": ["point", "blockSolid", 0, [2.0, 2.0]],
        'nX': ['point', 'Normals', 0, (-1, 1)],
        'nY': ['point', 'Normals', 1, (-1, 1)],
        'nZ': ['point', 'Normals', 2, (-1, 1)]
    }

    filters = []
    filters_description = []
    color_by = []

    filters.append(rodSurfaceNormals)
    filters_description.append({'name': 'Rod'})
    color_by.append([('VALUE', 'rodSolid'), ('VALUE', 'nX'), ('VALUE', 'nY'),
                     ('VALUE', 'nZ')])

    filters.append(blockFinsSurfaceNormals)
    filters_description.append({'name': 'Block/Fins'})
    color_by.append([('VALUE', 'blockSolid'), ('VALUE', 'nX'), ('VALUE', 'nY'),
                     ('VALUE', 'nZ')])

    for field in contours:
        for iso in contours[field]:
            filters_description.append({
                'name':
                field[0] + "=" + str(iso.Isosurfaces[0]),
                'parent':
                "Contour by %s" % field
            })
            filters.append(iso)
            color_by.append(iso_color_array)

    groupNumber = 1

    ### Create streamlines

    # create a new 'Calculator'
    velScaler = Calculator(Input=readerTransform)
    velScaler.ResultArrayName = 'scaledVel'
    functionString = '(%d*vel_X*iHat)+(%d*vel_Y*jHat)+(vel_Z*kHat)' % (
        transformDims[sizeOption][0], transformDims[sizeOption][1])
    velScaler.Function = functionString

    # create a new 'Stream Tracer'
    pointPair = seedLinePoints[sizeOption]
    streamTracer = StreamTracer(Input=velScaler,
                                SeedType='High Resolution Line Source')
    streamTracer.Vectors = ['POINTS', 'scaledVel']
    streamTracer.MaximumStreamlineLength = streamLength[sizeOption]

    # init the 'High Resolution Line Source' selected for 'SeedType'
    streamTracer.SeedType.Point1 = pointPair['point1']
    streamTracer.SeedType.Point2 = pointPair['point2']
    streamTracer.SeedType.Resolution = streamRes[sizeOption]

    # create a new 'Tube'
    tube = Tube(Input=streamTracer)
    tube.Scalars = ['POINTS', 'AngularVelocity']
    tube.Vectors = ['POINTS', 'Normals']
    tube.Radius = tubeRadius[sizeOption]
    tube.VaryRadius = 'By Vector'
    tube.RadiusFactor = 0.1

    # create a new 'Extract Surface'
    extractTubeSurface = ExtractSurface(Input=tube)

    # create a new 'Calculator'
    calculator = Calculator(Input=extractTubeSurface)
    calculator.ResultArrayName = 'Normals'
    calculator.Function = 'TubeNormals'

    filters.append(calculator)
    filters_description.append({'name': 'Streamlines'})
    color_by.append(iso_color_array)

    # Create the image exporter
    exporter = wx.CompositeImageExporter(fng,
                                         filters,
                                         color_by,
                                         luts,
                                         camera_handler,
                                         [resolution, resolution],
                                         filters_description,
                                         format='png')  #, 0, 0)

    # Customize some view properties
    exporter.view.Background = [1.0, 1.0, 1.0]
    exporter.view.OrientationAxesVisibility = 0
    exporter.view.CenterAxesVisibility = 0

    # -----------------------------------------------------------------------------
    # Perform analysis
    # -----------------------------------------------------------------------------

    for t in fileTimes:
        time = int(t)
        GetAnimationScene().TimeKeeper.Time = float(time)
        fng.update_active_arguments(time=time)
        exporter.UpdatePipeline(time)