This is a read-only mirror of pymolwiki.org

Difference between revisions of "Plugins Tutorial"

From PyMOL Wiki
Jump to navigation Jump to search
(add instructions to work with more than one file)
m (add see also Plugins)
Line 149: Line 149:
 
sys.path.append(path)
 
sys.path.append(path)
 
</source>
 
</source>
 +
 +
=SEE ALSO=
 +
[[Plugins]]
  
 
[[Category:Developers|Plugins_Tutorial]]
 
[[Category:Developers|Plugins_Tutorial]]
 
[[Category:Plugins|Plugins_Tutorial]]
 
[[Category:Plugins|Plugins_Tutorial]]
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]

Revision as of 08:06, 22 September 2015

Installing Plugins

To install a plugin, simply save the plugin file and load it into PyMol with the Plugin -> Install Plugin... menu item. Alternatively, plugins can be installed by copying the file into the PYMOLPATH/module/pmg_tk/startup/ folder.


Writing Plugins: Learn By Example

This tutorial is a more sophisticated version of the PDB Loader Service plugin that is bundled with PyMol. It is a relatively simple plugin, but should prove to be a good starting point for developing new plugins.

Registering your Plugin

First you must add your plugin to the Plugins menu. This is most easily done in the __init__ method of your plugin. A callback, fetchPDBDialog, is added. It is passed a reference to the main Tk app. It will need this in order to create new content in the main Tkinter loop. It is not strictly required in this example, but is needed in more complex interfaces.

 def __init__(self):
    self.menuBar.addmenuitem('Plugin', 'command',
                             'PDB Loader Service',
                             label = 'PDB Loader Service',
                             command = lambda s=self : fetchPDBDialog(s))

Adding Functionality

For this example we are going to dynamically download, from the Protein Data Bank, a molecular structure and then load it into the PyMOL interface. Here is a simple method which does that, given a PDB-ID (pdbCode).

 def remote(pdbCode):
    pdbCode = pdbCode.upper()
    try:
       pdbFile = urllib2.urlopen('http://www.rcsb.org/pdb/cgi/export.cgi/' +
                                 pdbCode + '.pdb.gz?format=PDB&pdbId=' +
                                 pdbCode + '&compression=gz')
       cmd.read_pdbstr(zlib.decompress(pdbFile.read()[22:], -zlib.MAX_WBITS), pdbCode)
    except:
       print "Unexpected error:", sys.exc_info()[0]
       tkMessageBox.showerror('Invalid Code',
                              'You entered an invalid pdb code:' + pdbCode)

Creating the Interface

Now we need to write the callback method, fetchPDBDialog, which creates the interface.

 def fetchPDBDialog(app):
    pdbCode = tkSimpleDialog.askstring('PDB Loader Service',
                                       'Please enter a 4-digit pdb code:',
                                       parent=app.root)
    remote(pdbCode)

Pretty simple! As of now you have a fully functional plugin that will prompt the user for a pdb code, download it from Protein Data Bank, and load it into the PyMOL interface.

Extending Plugins to the Command Line

Opening the dialog can be tedious, so let's add a command line callback to make use of this new functionality.

 cmd.extend('remote', remote)

Now you can type something like this:

remote 1di9

to load the the corresponding pdb.

Full Source

Here is the complete example. You can save this file and load it into PyMol with the Plugin -> Install Plugin... menu item. The example also includes the sample license that Warren provides for plugin developers. It is optional, of course. You can read here about other open-source licenses you could use for your own project.

# Copyright Notice
# ================
# 
# The PyMOL Plugin source code in this file is copyrighted, but you can
# freely use and copy it as long as you don't change or remove any of
# the copyright notices.
# 
# ----------------------------------------------------------------------
# This PyMOL Plugin is Copyright (C) 2004 by Charles Moad <cmoad@indiana.edu>
# 
#                        All Rights Reserved
# 
# Permission to use, copy, modify, distribute, and distribute modified
# versions of this software and its documentation for any purpose and
# without fee is hereby granted, provided that the above copyright
# notice appear in all copies and that both the copyright notice and
# this permission notice appear in supporting documentation, and that
# the name(s) of the author(s) not be used in advertising or publicity
# pertaining to distribution of the software without specific, written
# prior permission.
# 
# THE AUTHOR(S) DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN
# NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# ----------------------------------------------------------------------

import tkSimpleDialog
import tkMessageBox
from pymol import cmd
import sys, urllib2, zlib

def __init__(self):
   self.menuBar.addmenuitem('Plugin', 'command',
                            'PDB Loader Service',
                            label = 'PDB Loader Service',
                            command = lambda s=self : fetchPDBDialog(s))

def remote(pdbCode):
   pdbCode = pdbCode.upper()
   try:
      pdbFile = urllib2.urlopen('http://www.rcsb.org/pdb/cgi/export.cgi/' +
                                pdbCode + '.pdb.gz?format=PDB&pdbId=' +
                                pdbCode + '&compression=gz')
      cmd.read_pdbstr(zlib.decompress(pdbFile.read()[22:], -zlib.MAX_WBITS), pdbCode)
   except:
      print "Unexpected error:", sys.exc_info()[0]
      tkMessageBox.showerror('Invalid Code',
                             'You entered an invalid pdb code:' + pdbCode)

def fetchPDBDialog(app):
   pdbCode = tkSimpleDialog.askstring('PDB Loader Service',
                                      'Please enter a 4-digit pdb code:',
                                      parent=app.root)
   
   remote(pdbCode)

cmd.extend('remote', remote)


Working with more than one file

Plugins are not limited to one file. It is possible to have more than one .py file or even data files or directories. In order to distribute your multi-file plugin you should put all the necessary files into a folder (named after your plugin's name) and then zip it. You will distribute your plugin as a .zip file. The PyMOL plugin manager is able to install the .zip file.

Inside the folder with the name of your plugin you should put the followings files:

  • __init__.py (this should be the main file, the one with the instructions to register the plugin)
  • data files (optional)
  • directories (optional)
  • other .py files (optional)

To locate your data files (if any) add the following line inside the __init__.py file

path = os.path.dirname(__file__)

and the following line if your plugin consist of more that one .py file.

sys.path.append(path)

SEE ALSO

Plugins