Adding new plots to UVCDAT
Clone this wiki locally
In this tutorial we show how to add a new plot to UV-CDAT.
- Working installation of UVCDAT 1.3 or greater
- [UVCDAT 1.3 only] VisTrails submodule updated to commit 655ee329277d7e9412ee5cbe15c76bc4a322c236
- Create VisTrails Pipeline
- Register Plot with UV-CDAT
- Create a PipelineHelper
Step 1 - Create VisTrails Pipeline
Open UVCDAT, and make a simple plot to use as a starting point for your custom plot pipeline.
- In this example we create a VCS-BoxPlot-ASD using the 'clt' variable from file 'clt.nc' (located in UVCDAT's sample_data directory).
From the main menu, select
VisTrails > Builderto bring up the VisTrails Builder window.
Build your custom plot pipeline
- We just use a PythonSource module to produce custom behavior. Another option is to add custom packages to VisTrails (see http://www.vistrails.org/usersguide/v2.0/html/packages.html)
- Our plot is based off of a numpy vtk example http://www.vtk.org/Wiki/VTK/Examples/Python/vtkWithNumpy
- Since UVCDAT is based around the CDMS variable, which is based on numpy, we just needed to extract the numpy array from cdms to use with this vtk example. This step was done using a python source module in VisTrails with the following configuration
- And using the following source
from numpy import uint8, ndarray import vtk #get the cdms transient variable object from the CDMSVariable module cdms_var = var_module.var #get the underlying numpy array numpy_arr = cdms_var.data #convert array to uint8 for use with vtk data_matrix = numpy_arr.astype(uint8) # For VTK to be able to use the data, it must be stored as a VTK-image. This can be done by the # vtkImageImport-class which imports raw data and stores it. dataImporter = image_import_in.vtkInstance # The preaviusly created array is converted to a string of chars and imported. data_string = data_matrix.tostring() dataImporter.CopyImportVoidPointer(data_string, len(data_string)) # The type of the newly imported data is set to unsigned char (uint8) dataImporter.SetDataScalarTypeToUnsignedChar() # Because the data that is imported only contains an intensity value (it isnt RGB-coded or something # similar), the importer must be told this is the case. dataImporter.SetNumberOfScalarComponents(1) #get extents of array for vtk, and make sure we have the right dimensions ext1 = len(numpy_arr)-1 if isinstance(numpy_arr, ndarray): ext2 = len(numpy_arr)-1 if isinstance(numpy_arr, ndarray): ext3 = len(numpy_arr)-1 if isinstance(numpy_arr, ndarray): raise Exception("Expecting 3D data, got 4D or greater instead") else: raise Exception("Expecting 3D data, got 2D instead") else: raise Exception("Expecting 3D data, got 1D instead") extents = [0, ext1, 0, ext2, 0, ext3] # The following two functions describe how the data is stored and the dimensions of the array it is # stored in. I have to admit however, that I honestly dont know the difference between # SetDataExtent() and SetWholeExtent() although VTK complains if not both are used. dataImporter.SetDataExtent(*extents) dataImporter.SetWholeExtent(*extents) image_import = image_import_in
+ The rest of the pipeline was built to mimic the python code in the vtk example![Complete Plot Pipeline](http://i.imgur.com/pdVjSVa.jpg)
Execute your custom plot pipeline to make sure it works and you get the desired result in the UV-CDAT spreadsheet.
Important When you're happy with your results, go back to the VisTrails Builder window and remove the CDMSVariable and CellLocation modules. These modules are generated by UV-CDAT. (Notice the two missing modules in the following image, marked by yellow rectangles)
From the VisTrails builder, save your vistrail (we named ours TranslucentVolume.vt)
Step 2 - Register Plot with UV-CDAT
Now that we have a plot, we need to add it to UV-CDAT's registry. This is located at <uvcdat_dir>/vistrails/vistrails/core/uvcdat/plots. This folder contains all of the plot packages.
- Create a new folder with the name of the package you are creating (e.g. 'NewVTK')
- Copy the vt file generated in the previous step into this folder
- `cp ~/Documents/TranslucentVolume.vt NewVTK/
- Create a new configuration file for the plot in the same folder
[global] cellnum = 1 filenum = 1 varnum = 1 dependencies = edu.utah.sci.vistrails.vtk
+ This basically just says our plot uses one cell, one variable, and depends on the vtk package
- Create a package registry config file in the same folder
[Translucent Volume] config_file = TranslucentVolume.cfg vt_file = TranslucentVolume.vt
+ The name in the brackets is what users will see in the gui
- Add the package to the bottom of the main registry file (one level above the NewVTK dir)
... [NewVTK] codepath = NewVTK config_file = registry.cfg helper = core.uvcdat.plots.NewVTK.NewVTKPipelineHelper
+ The last line references the PipelineHelper we are about to create. Normally these are defined inside of the VisTrails package definitions, but since we didn't create a new VisTrails package for this example, we'll just place it inside our NewVTK folder.
Step 3 - Create a PipelineHelper
The PipelineHelper is the glue needed to match variable module to the plot pipeline we just created. In this case it is fairly simple, but it can be more complicated when multiple variables are involved.
- Create a new python file in the package registry folder we just created
from packages.uvcdat_cdms.pipeline_helper import CDMSPipelineHelper class NewVTKPipelineHelper(CDMSPipelineHelper): @staticmethod def build_plot_pipeline_action(controller, version, var_modules, plots,row, col, template=None): # only support one plot plot = plots # This function copies all of the modules and connections from the # vt file specified in the plot registry config. It returns all # the generated pipeline items, as well as a list of ports that # accept a CDMSVariable in the pipeline. pipeline_items, cdms_ports = \ CDMSPipelineHelper.create_plot_workflow_items( plot.workflow, controller, row, col) # We need to match variable modules to the ports returned in above call. # Since our plot only works on a single variable, we'll just match the # first in each list. variable_matches = [(var_modules, cdms_ports)] #finalize pipeline creation action = CDMSPipelineHelper.finish_plot_workflow(controller, pipeline_items, variable_matches, version) return action
Now you should be able to use your plot in UVCDAT.
All of the files used in this example can be found on branch uvcdat-add-new-plot-example of the VisTrails repository.