Plugins Tutorial

From PyMOLWiki
Jump to navigation Jump to search

This tutorial is about writing your own plugin for PyMOL 2.x.

See the plugins page for how to install and use exisiting plugins.

Writing Plugins: Learn By Example

This tutorial shows how to write a PyMOL plugin with PyQt. The full source of the demo plugin is available on github.

The demo plugin adds a dialog to render images at a custom resolution.

Plugin Files

We will create a plugin which consists of multiple files inside a directory:

pymol2-demo-plugin/
├── demowidget.ui
└── __init__.py (defines "__init_plugin__(app=None)" function)

Registering your Plugin

First you must add your plugin to the Plugins menu. This is done in the __init_plugin__ function of your plugin. A callback (here: run_plugin_gui) is added.

# file pymol2-demo-plugin/__init__.py
def __init_plugin__(app=None):
    from pymol.plugins import addmenuitemqt
    addmenuitemqt('Demo "Render" Plugin', run_plugin_gui)

Legacy note: The __init_plugin__ function takes one argument, a reference to the main Tk app to support legacy plugins witten with Tkinter (unused with PyQt plugins).

Creating a GUI

The callback may do arbitrary stuff. Here we're going to create a dialog and show it to the user.

# global reference to avoid garbage collection of our dialog
dialog = None

def run_plugin_gui():
    # pymol.Qt provides the PyQt5 interface, but may support PyQt4 and/or PySide as well
    from pymol.Qt import QtWidgets

    global dialog

    if dialog is None:
        # create a new (empty) Window
        dialog = QtWidgets.QDialog()

        # TODO: FILL DIALOG WITH WIDGETS HERE

    dialog.show()

Filling the GUI with Widgets

Screenshot of Qt Designer

The most convenient and maintainable way to create user interfaces with Qt is by using the Qt Designer. Follow these steps to get started:

  1. Create a new "Widget" form (New Form > templates/forms > Widget > Create)
  2. Drag widgets like "Push Button" or "Line Edit" into your form
  3. Name your widgets ("objectName" in the "Property Editor"), this name will become a Python variable in your code
  4. Save as a UI file (*.ui) inside the pymol2-demo-plugin directory

PyMOL provides a utility function to load a UI file into a parent widget: pymol.Qt.utils.loadUi(filename, widget)

    # filename of our UI file
    uifile = os.path.join(os.path.dirname(__file__), 'demowidget.ui')

    # load the UI file into our dialog
    from pymol.Qt.utils import loadUi
    form = loadUi(uifile, dialog)

Make Buttons do something

We need to connect the signals of those widgets we created with the Qt Designer, like our buttons' clicked signal. Our example has a "Ray" button (objectName=button_ray) that we'll connect to the run() function.

    def run():
        # get form data
        height = form.input_height.value()

        # some debugging feedback
        print('User entered height', height)

        # TODO: DO SOMETHING WITH FORM DATA

    form.button_ray.clicked.connect(run)

Deploy the final plugin

The pymol2-demo-plugin directory can be zipped for deployment (see PluginArchitecture#More than one file per plugin).

Full Source

The full source of the demo plugin is available on github.

Extending Plugins to the Command Line

While not really applicable to our simple "Render" plugin (it only wraps existing ray and png commands), most plugins should also provide their functionality as new PyMOL commands using cmd.extend().

See Also