Leap Motion
Jump to navigation
Jump to search
This page describes how to get the Leap Motion Controller working in PyMOL, using the Leap Python API. The script was tested with PyMOL 2.0 on all platforms, with MacPyMOL "syspython", and with Open-Source PyMOL on Gentoo Linux and MacOS.
Using PyMOL 2.0 (Anaconda Python)
Install the driver from https://www.leapmotion.com/setup/desktop/
Install PyMOL and the Leap Python module from Anaconda Cloud:
conda install -c schrodinger pymol conda install -c speleo3 leap-motion-python
Using Open-Source PyMOL on MacOS
Experienced Issues
- must use /usr/bin/python2.7, the macports or fink python does not work
- must use GLUT framework, macports or fink X11 glut will not work
- the GLUT framework will change the current directory on startup
- no Tk (external window)
Compiling and Running PyMOL on OSX
In SVN rev 4037 there was a --osx-frameworks argument added to use OpenGL and GLUT frameworks. See also Linux Install.
/usr/bin/python2.7 setup.py build install \
--prefix=/tmp/pymol-for-leapmotion \
--osx-frameworks
Run PyMOL without the external GUI and provide absolute paths for arguments:
/tmp/pymol-for-leapmotion/bin/pymol -xqr $PWD/LeapExampleScript.py
Example Script
The script below demostrates proof-of-concept by implementing camera rotation and zooming with multiple fingers. It's not supposed to provide real production functionality.
'''
Minimal example for PyMOL + LEAP Motion
(c) 2013 Schrödinger, Inc.
License: BSD-2-Clause
'''
import sys
import math
from pymol import cmd
if sys.platform.startswith('linux'):
sys.path.append('/usr/share/Leap/LeapSDK/lib')
sys.path.append('/usr/share/Leap/LeapSDK/lib/x64')
else:
# TODO: ADJUST THIS
sys.path.append('/path/to/LeapSDK/lib')
import Leap
from Leap import Matrix, Vector
class PymolListener(Leap.Listener):
def __init__(self, *args, **kwargs):
super(PymolListener, self).__init__(*args, **kwargs)
self.prev_frame = None
self.controller = Leap.Controller()
self.controller.add_listener(self)
def __del__(self):
self.controller.remove_listener(self)
super(PymolListener, self).__del__()
def update_view(self, frame):
if not self.prev_frame:
return
view = list(cmd.get_view())
if frame.rotation_probability(self.prev_frame) > 0.1:
m = frame.rotation_matrix(self.prev_frame)
m *= Matrix(Vector(*view[0:3]),
Vector(*view[3:6]),
Vector(*view[6:9]))
view[:9] = m.to_array_3x3()
if frame.scale_probability(self.prev_frame) > 0.1:
s = frame.scale_factor(self.prev_frame)
delta_z = math.log(s) * 100.0
view[11] += delta_z
view[15] -= delta_z
view[16] -= delta_z
cmd.set_view(view)
def on_frame(self, controller):
frame = controller.frame()
self.update_view(frame)
self.prev_frame = frame
listener = PymolListener()