Skip to content

Commit

Permalink
Merge pull request #50 from Autodesk/rc_fixes
Browse files Browse the repository at this point in the history
Update README, better notebook extension installation
  • Loading branch information
avirshup authored Aug 10, 2017
2 parents 1abd45e + 6801d22 commit 48e97b0
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 29 deletions.
72 changes: 59 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,92 @@ notebook-molecular-visualization
===============================
[![PyPI version](https://badge.fury.io/py/nbmolviz.svg)](https://badge.fury.io/py/nbmolviz)

A Python widgets library for 2D and 3D molecular visualization in Jupyter notebooks
Jupyter notebook add-ons for the [Molecular Design Toolkit](https://github.com/Autodesk/molecular-design-toolkit). NBMolViz provides visualization and interactivity for 3D Molecular Structures in Jupyter notebooks.

After installing it, you'll never need to use the NBMolViz package directly. It's instead called through MDT to provide enhanced functionality in notebooks.

## Installation
When you install `nbmolviz`, you'll need to both install the python library _and_ enable the notebook extensions.

1. **Install the python library:**
```bash
$ pip install nbmolviz
$ jupyter nbextension enable --python --system nbmolviz
$ jupyter nbextension enable --python --system widgetsnbextension
```

2. **Activate notebook extensions:**
To enable for your user account:
```bash
$ python -m nbmolviz activate --user
```
To enable within your current virtual environment:
```bash
$ python -m nbmolviz activate --sys-prefix
```

To globally enable for all users (use with caution! This may require `sudo`):
```bash
$ python -m nbmolviz activate --global
```

## Upgrading from older versions

1. **Upgrade the library to the newest version**
$ pip install --upgrade nbmolviz

2. **Remove old notebook extensions (you will be notified if it's necessary to run with `sudo`)**:
```bash
$ python -m nbmolviz clean-all
```


## Examples

To draw an OpenBabel molecule:
Draw a small molecule:
```python
import moldesign as mdt
mol = mdt.from_name('ethylene')
mol.draw()
```
<img src="img/smallmol.png" style="width: 600px;"/>

Draw a protein:
```python
import nbmolviz
import pybel
benzene = pybel.read_string('smi','c1cccc1').next()
nbmolviz.visualize(benzene)
import moldesign as mdt
mol = mdt.from_pdb('3aid')
mol.draw()
```
<img src="img/protein.png style="width: 600px;"/>


Interactively select atoms (the currently selected atoms will be available as `selector.selected_atoms`)
```python
import moldesign as mdt
mol = mdt.from_pdb('3aid')
selector = mdt.widgets.ResidueSelector(mol)
selector
```
<img src="img/selector.png" style="width: 600px;"/>


## Dev install
Requires npm.

$ git clone https://github.com/autodesk/notebook-molecular-visualization.git
$ git clone https://github.com/autodesk/notebook-molecular-visualization
$ cd notebook-molecular-visualization
# ./set_filters.sh # tells git to clean up notebooks before committing
$ python setup.py jsdeps
$ pip install -e .
$ jupyter nbextension install --py --symlink --user nbmolviz
$ jupyter nbextension enable --py --user nbmolviz
$ cd tests/galileo && npm install

This will build your widgets into a folder at `notebook-molecular-visualization/nbmolviz/static`

During development, to see the effects of changes to any javascript files (in notebook-molecular/visualization/js/src), run `python setup.py jsdeps` and reload any notebook browser windows.

## Tests
Run tests with:

pytest nbmolviz/_tests
## To run visual tests
`cd tests/nb && ../galileo/bin/galileo --launchnb`

## Releasing a new version
Travis automatically releases commits that are tagged, so to trigger a new release, just do:
Expand Down
Binary file added img/protein.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/selector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/smallmol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 107 additions & 0 deletions nbmolviz/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from __future__ import print_function, absolute_import, division
from future.builtins import *
from future import standard_library
standard_library.install_aliases()

# Copyright 2017 Autodesk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
import argparse

class SmartFormatter(argparse.HelpFormatter):
"""
From https://stackoverflow.com/a/22157136/1958900
"""
def _split_lines(self, text, width):
if text.startswith('R|'):
return text[2:].splitlines()
# this is the RawTextHelpFormatter._split_lines
return argparse.HelpFormatter._split_lines(self, text, width)

def main():
from . import install, _version
parser = argparse.ArgumentParser('python -m nbmolviz', formatter_class=SmartFormatter)

parser.add_argument('command', choices=['activate', 'uninstall', 'check'],
help='R|activate - install and enable nbmolviz\n'
'uninstall - remove old nbmolviz installations\n'
'check - check installed versions\n')

group = parser.add_mutually_exclusive_group()
group.add_argument('--sys-prefix', '--env', '--venv', action='store_true',
help="Apply command to your virtual environment")
group.add_argument('--user', action='store_true',
help="Apply command to all of this user's environments")
group.add_argument('--sys', '--global', '--system', action='store_true',
help="Apply command to the global system configuration")

args = parser.parse_args()

if args.command == 'check':
print('Expected version:', _version.get_versions()['version'])
versions = install.get_installed_versions('nbmolviz-js', True)
foundone = False
for key, vers in versions.items():
if vers.installed:
if foundone:
print('--')
else:
foundone = True
print('Installed notebook extension locations:\n')

if key == 'user':
print('Environment:', 'current user')
elif key == 'environment':
print('Environment:', 'current virtual environment')
else:
assert key == 'system'
print('Environment:', 'global / system-wide')

print('Version: ', vers.version)
print('Location: ', vers.path)

if not foundone:
print("NBMolViz Jupyter extensions are not installed in any current environments")

elif args.command == 'activate':
if not (args.sys_prefix or args.user or args.sys):
print('Please indicate which environment to activate nbmolviz in.')
parser.print_help()
sys.exit(10)

if args.sys_prefix:
install.activate('--sys-prefix')
if args.user:
install.activate('--user')
if args.sys:
install.activate('--system')

elif args.command == 'uninstall':
if not (args.sys_prefix or args.user or args.sys):
args.sys_prefix = args.user = args.sys = True

if args.sys_prefix:
install.uninstall('--sys-prefix')
if args.user:
install.uninstall('--user')
if args.sys:
install.uninstall('--system')

else:
assert False, "parser failure"


if __name__ == '__main__':
main()
52 changes: 36 additions & 16 deletions nbmolviz/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import os
import sys
import collections
import subprocess

import nbmolviz

Expand All @@ -28,24 +29,13 @@
NbExtVersion = collections.namedtuple('NbExtVersion', 'name installed path version'.split())


def nbextension_check(extname, getversion):
def get_installed_versions(extname, getversion):
""" Check if the required NBExtensions are installed. If not, prompt user for action.
"""
import jupyter_core.paths as jupypaths
from notebook import nbextensions

# TODO: implement the following:
# 0. Resolve jupyter nbextension search path, find installed
# jupyter-js-widgets and nbmolviz-js extensions and their versions
# 1. If extension with correct version is installed and enabled, do nothing, we're done
# 2. If correct extensions are installed but not enabled, prompt user to enable
# 3. If there are multiple copies, and the wrong version(s) are enabled, prompt user to
# enable the right ones
# 4. If not installed, prompt user to install/enable in the first writeable instance of
# the following: sys-prefix, user-dir, systemwide
# see https://github.com/ipython-contrib/jupyter_contrib_nbextensions/blob/master/src/jupyter_contrib_nbextensions/install.py

installed = {k: nbextensions.check_nbextension('nbmolviz-js', **kwargs) for k,kwargs in EXTENSION_KWARGS.items()}
installed = {k: nbextensions.check_nbextension(extname, **kwargs) for k,kwargs in EXTENSION_KWARGS.items()}
jupyter_dir = {'user': jupypaths.jupyter_data_dir(),
'environment': jupypaths.ENV_JUPYTER_PATH[0],
'system': jupypaths.SYSTEM_JUPYTER_PATH[0]}
Expand All @@ -63,12 +53,43 @@ def nbextension_check(extname, getversion):
with open(versionfile, 'r') as pfile:
versions[k] = pfile.read().strip()
else:
versions[k] = 'pre-0.8'
versions[k] = 'pre-0.7'

return {k: NbExtVersion(extname, installed[k], paths.get(k, None), versions.get(k, None))
for k in installed}


def activate(flags):
try:
_jnbextrun('install', 'widgetsnbextension', flags)
_jnbextrun('enable', 'widgetsnbextension', flags)
except subprocess.CalledProcessError as exc:
if exc.returncode == 2:
print(('ERROR - failed to enable the widget extensions with %s.' % flags) +
' Try rerunning the command with \"sudo\"!')
sys.exit(2)

_jnbextrun('install', 'nbmolviz', flags)
_jnbextrun('enable', 'nbmolviz', flags)


def uninstall(flags):
try:
_jnbextrun('disable', 'nbmolviz', flags)
_jnbextrun('uninstall', 'nbmolviz', flags)
except subprocess.CalledProcessError as exc:
if exc.returncode == 2:
print(('ERROR - failed to uninstall the widget extensions with %s.' % flags) +
' Try rerunning the command with \"sudo\"!')
sys.exit(2)


def _jnbextrun(cmd, lib, flags):
shellcmd = ['jupyter', 'nbextension', cmd, '--py', flags, lib]
print('> %s' % ' '.join(shellcmd))
subprocess.check_call(shellcmd)


def find_nbmolviz_extension(extname):
import jupyter_core.paths as jupypaths
for extpath in jupypaths.jupyter_path('nbextensions'):
Expand All @@ -77,4 +98,3 @@ def find_nbmolviz_extension(extname):
return extpath
else:
return None

Loading

0 comments on commit 48e97b0

Please sign in to comment.