Extending MayaVi

User defined sources, modules and filters

The easiest way to extend MayaVi is to create a directory that contains three sub-directories called Sources/ , Modules/ and a Filters/ directory inside where user defined sources, modules and filters can be stored. You don't need to create an __init__.py file in these directories. This directory should then be added to the MayaVi "search path" which may be set by using the Options/Preferences menu. The search path is a ':'-separated string and is specified like the PYTHONPATH. '~', '~user' and '$VAR' are all expanded. Note that after changing the search path you'll have to restart MayaVi.

These user defined modules and filters will be made available inside the User sub-menu of the File/Open, Module and Filter menus respectively. These sources, modules and filters can be used from the command line or from a Python interpreter session by using 'User.SourceName' (sources cannot be specified from the command line but may be specified in a Python script), 'User.ModuleName' or 'User.FilterName'. When creating user defined sources or modules or filters make sure that the name of the module is the same as the name of the class that defines the particular object.

It is likely that the first thing you will do to test out this functionality is to copy a standard source, module or filter into your directory, rename it and test with it. Beware of some of the following points before you do that.

  1. Make certain that the name of the class that defines the source/module/filter is identical with the name of the module that contains it. So if you have a module called MySuperModule.py the class that defines the module must be called MySuperModule. The same applies to the sources and filters as well.

  2. The standard Modules/filters and sources are a little special and will typically contain code that looks like this.

    import Base.Objects, Common
    # ...
    class SomeModule(Base.Objects.Module):
    # ...
    

    This must be changed to the following.

    from mayavi import Common
    from mayavi.Base import Objects
    # ...
    class SomeModule(Objects.Module):
    # ...
    

    Essentially, the Python module defining your object should be "import-able" from the Python interpreter even without MayaVi running.

General guidelines and information

This section lists a set of things that developers should know before extending MayaVi by implementing new Modules, Sources and Filters.

  1. The print_err function takes a string and prints it out on a GUI message box.

  2. The get_relative_file_name(base_f_name, f_name) function returns a file name for the given f_name relative to the base_f_name. This is useful when one stores file names in the configuration.

  3. The get_abs_file_name(base_f_name, rel_f_name) function returns an absolute file name given a base file name and another file name relative to the base name. This is useful to load a stored file name.

  4. The debug function prints a string on the debug window and on sys.stdout. This is used to print debug messages in all the MayaVi code.

  5. The config variable is an instance of class that contains the configuration preferences of the user. This is used to initialize default colors etc.

  6. The state variable is instance of the AppState class. The state.busy() state.idle() members are used to change the state of the MayaVi application.

  1. As with any code the best way to learn how the classes and functions are organized and work is to look through the source. What follows are a few hints that might be useful when you develop code for MayaVi.

  2. Before writing a new component please look at the the Module, Filter and Source classes defined in Base/Objects.py. Also look at their parent classes. A lot of useful functionality is provided there and reading this may prevent unnecessary code replication.

  3. The Module and Filter menus are created dynamically from the files in the Modules and Filters directories. All the files there except the __init__.py will be recognized as modules or filters respectively. So do not put any files there that are neither modules nor filters.

  4. Make sure the name of the new Module/Filter or Source subclass and the name of the file that defines the Module subclass are the same. For instance the Axes module is defined in a file called Axes.py.

  5. As far as possible try to follow my style of coding. The naming convention that I have followed is to name all VTK like methods in the usual VTK way (like GetOutput). All other methods are named like so get_vtk_object. This has been done to differentiate between the two. All class names have the first letter of each word capitalized for example as in VtkDataReader and ExtractVectorComponents.

  6. Please try to document your classes and functions.

  7. While writing any component please try to make the particular component "import safe" by not doing either of the first two and using the last way of importing modules. Doing this makes it possible to reload modules on the fly.

    # Don't do this:
    from SomeThing import *
    # or the following:
    from SomeThing import SomeClass
    # Use this instead.
    import SomeThing
    
  8. While developing a component it is possible to test the component by running MayaVi and then retest it by reloading the modules from the Options.

  9. The Common.py module provides a few useful classes and functions. Some of them are as follows:

  10. Every component has to be able to save its state to an ASCII file and be able to reload its state from the saved file. The save_config and load_config functions should implement this. This should be tested properly.

Happy hacking!