GRaphical Abstracted Protein Explorer (GRAPE) GRAPE Viewer plugin documentation Overview: This is a plugin for PyMol that can load and render molecular visualizations created on http://grape.uwbacter.org/ It is based on the java renderer used on GRAPE's website, written by Greg Cipriano. The plugin may load a zip file of abstraction data and render it directly in Pymol, with updates applied to OpenGL itself. HUGE WARNING: Because the XML data inside the zip file is located based on the name of the zip file, you cannot rename the zip file and have it load. It's advised to put visualizations into a unique directory for whatever surface you want to look at, rather than rename the zip file. Installation: Firstly, you need an updated copy of PyOpenGL installed on your system. Essentially, you can build one with the same tools used to build Pymol and then drop it into the pymol Just ensure you're using the same version of python that your pymol was built with and whatever C++ compiler, in case of compatibility issues. On Tom's linux system - this was done by going into the pymol folder and finding: /python2.6/site-packages/pymol/opengl The same can be done on a Mac and Windows easily. Jordan has already done it on the machines we've tested on in the lab. Replacing this folder with the data from a newer pyopengl should cover things. On case sensitive file systems, you might need to ensure that opengl/gl opengl/glu and such are all lowercase. Pymol ships with them lower case, but pyopengl builds don't necessarily do that. Also, in order to run, on Mac or Linux you may have to export PYTHONPATH=$PYTHONPATH:$HOME so python can find the GRAPE_Path_File.py that the plugin creates. Any shortcuts should probably be updated with this. Copy the folder with the GRAPE plugin somewhere on your system, where the user has permissions. "Install" in pymol: In the TK window, go to Plugin->Manage Plugins->Install... and point it to GRAPE_Plugin.py This will copy the GRAPE_Plugin.py file into pymol's internal python folders, so any changes to this file only require you to Remove and Install it again via pymol's menus. Change to the other GRAPE files won't need such an update. Restart pymol After installation, the plugin needs to know where the bulk of the actual plugin code exists. Plugin->GRAPE->Set New GRAPE Path Find GRAPE_Main.py in the folder that you put everything in before and point it there. Restart pymol. Now it should be "installed". It will put a file named GRAPE_Path_File.py in the users's home directory. This is a stop gap file needed for the GRAPE_Plugin.py to load the rest of the python code in the plugin. Running: To run it after it's installed, go to Plugin-> GRAPE-> Start GRAPE This will create a TK gui where you may then load an abstraction by going to File-> Load Molecule Select a file that's been downloaded from http://grape.uwbacter.org; It should be named something like decal-1234.zip It will take a moment to load the XML data, parse the PNG files, and create a visualization that you can then see on the screen. Code documentation (useful for hacking it) Here's a heirarchical view of the files and their classes in the GRAPE viewer: GRAPE_Plugin Grape_Main ViewerCallback MolecularSurfaceView SurfaceCollection Surface Vector3D SurfData Shape DecalList Decal Color Material SurfData TriangleMeshGeometry Vector2D Texture Appearance Shape TriangleMeshGeometry Material Color Appearance If you have CameraTestEnvironment.py and SimpleCamera.py in the code folders, you can simply delete them. They were remnants of old testing. Greg's original renderer made use of jogl heavily to ease rendering everything. For the most part, Tom has translated those classes into python equivalents. Some changes have been made to utilize other OpenGL features, as the default GL rendering is non-interactive without numpy or numeric and is generally slow in Python already. PyMol ships with a very dated copy of PyOpenGL, which will have to be updated on a client machine before this plugin entirely works. Pymol's plugin system allows very simple files to be added as plugins, but we can use python's extendibility to create a decent framework of classes to render our abstractions. The natural source for our classes is from Greg's original java renderer that is used on the grape website. This code might be useful as an original source for someone who wants to understand how this is all hacked together. So, in order to do OpenGL rendering pymol, it must be placed in a "callback" class that pymol will call whenever it refreshes the screen. ViewerCallback is the class that handles that. GRAPE_Plugin.py This is the file that needs to be "installed" in pymol. It will create a file called "GRAPE_Path_File.py", which the plugin uses to find the GRAPE_Main.py. This file is pretty OS agnostic at this point. Successfully ran it in Linux, Mac, and Windows systems. The path file simply allows python to load the Grape_Main.py GRAPE_Main.py: This is the main UI file. It utilizes TK to create the external GUI. It also initializes the "callback" class whenever we load a different visualization from a decal.zip file. The TK stuff here is pretty simple and can be updated/extended should other gui controls need to be added. Whenever a new file is loaded, it creates a new ViewerCallback class, to instantiate the visualization and render it. ViewerCallback.py: This is pymol's "callback" class for rendering. Whenever pymol updates, it will call ViewerCallback.__call__(self) and if it has a fully instantiated MolecularSurfaceView class, it will use it to render. MolecularSurfaceView.py: This is a catch all for all of the geometry and color combos used to render the abstraction. Each visualization view will hold a collection of Surfaces, either original geometry or abstracted surfaces along with their decals. When initializing, this will create a surface for each .ply file defined in the .xml file Example: Archive: decal-1867.zip inflating: decal-1867_00_0_A.face_abstracted.ply inflating: 000.png inflating: 001.png inflating: 002.png inflating: 003.png inflating: 004.png inflating: 005.png inflating: 006.png inflating: 007.png inflating: 008.png inflating: 009.png inflating: 010.png inflating: 011.png inflating: 012.png inflating: 013.png inflating: 014.png inflating: 015.png inflating: 016.png inflating: 017.png inflating: 018.png inflating: 019.png inflating: 020.png inflating: 021.png inflating: 022.png inflating: 023.png inflating: 024.png inflating: 025.png inflating: 026.png inflating: 027.png inflating: 028.png inflating: 029.png inflating: 030.png inflating: 031.png inflating: 032.png inflating: 033.png inflating: 034.png inflating: 035.png inflating: 036.png inflating: 037.png inflating: decal-1867_00_0_A.face.ply inflating: decal-1867_01_300_CA.face.ply inflating: decal-1867_02_301_CA.face.ply inflating: decal-1867_03_302_CA.face.ply inflating: decal-1867_04_303_C8E.face.ply inflating: decal-1867_05_304_C8E.face.ply inflating: decal-1867_06_305_C8E.face.ply inflating: decal-1867_07_306_C8E.face.ply inflating: decal-1867.xml MolecularSurfaceView.loadSurfaces(): will instantiate a Surface class for each abstracted and regular surface it finds in the decal-xxxx.xml file. Surface.py will then use the XML data for each separate surface and create the geometry and colors for that surface from the .ply file specified in the XML data. The above example has 8 surfaces with 1 abstracted surface for total of 9 surfaces. Besides the geometry for the surface, the abstracted surface will also create the geometry, color, and textures for the decal rendering as a DecalList class. All of the PLY data is in a little endian packed binary form. Surface.loadSurfacePLY(self, sd, plystring) will extract it into vertices, colors and faces, and the other classes will then chop them up for rendering. These are loaded into a "Shape" class instantiation, which holds geometry as well as color data. Decal, Color, Material, TriangleMeshGeometry, Vector2D, Texture, Appearance, Shape.py: These are all simple classes for instantiating the decal textures, and surface geometry. They're functional equivalents of what JoGL offers. TriangleMeshGeometry.py is the class that actually does the low level GL rendering. It is painfully slow at moving the color and triangle data to the video card, so it takes advantage of GL Lists. So, whenever a color is switched or the lighting is tweaked, it takes a second to update the GL list with the new color. Switching to using OpenGL buffers would probably improve this performance, but my attempts at doing it have failed with a lot of fighting between pymol and pyopengl. The DecalList is simply a copy of the geometry with texture information for each decal and all of its respective geometry. Render path: This is probably the important part to understand, if you want to follow where the code goes after everything is instantiated. GRAPE_Main.py sets an instantation of the ViewerCallback class as a pymol callback, so it will be called whenever pymol updates the screen or is forced to update via pymol.cmd.refresh() ViewerCallback calls its instantiation of a viewer via MolecularSurfaceView->Draw() MolecularSurfaceView->Draw() loops over each surface and renders it if it is visible via Surface.Render() Surface.Render() calls Shape.Render(), which will then preload the appropriate "appearance" info - colors, texture. Then it renders the Geometry via TriangleMeshGeometry->Render(). There, it will build a GL list if necessary, then render it. MolecularSurfaceView->Draw() loops over each surface and renders it if it is visible via Surface.TranslucentRender() This follows the same general path, but is rendering the decal geometry, in order to ensure z buffers and occlusion is correct.