Marcello-Sega/pytim

View on GitHub
README.md

Summary

Maintainability
Test Coverage
[What is Pytim](#what-is-pytim) | [Examples](#example) | [More info](#more-info)  | [How to Install](#installation) | [References](#references)


[![Build Status](https://api.travis-ci.com/Marcello-Sega/pytim.svg?branch=master)](https://travis-ci.com/Marcello-Sega/pytim)
[![GitHub tags](https://img.shields.io/github/tag/Marcello-Sega/pytim.svg)](https://github.com/Marcello-Sega/pytim/)
[![GitHub issues](https://img.shields.io/github/issues/Marcello-Sega/pytim.svg)](https://github.com/Marcello-Sega/pytim/issues)
[![codecov](https://codecov.io/gh/Marcello-Sega/pytim/branch/master/graph/badge.svg)](https://codecov.io/gh/Marcello-Sega/pytim)
[![Code Climate](https://codeclimate.com/github/Marcello-Sega/pytim/badges/gpa.svg)](https://codeclimate.com/github/Marcello-Sega/pytim)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

<sub> If you try this software out and have some suggestions, remarks, or bugfixes, feel free to comment here on GitHub and/or make a pull request. </sub>

**Jupyter Notebooks** with _more examples_ are available at [Marcello-Sega/pytim-notebooks](https://github.com/Marcello-Sega/pytim-notebooks)

**The paper about pytim** has been published on J. Comput. Chem. It is open access and you can [download the pdf](https://onlinelibrary.wiley.com/doi/epdf/10.1002/jcc.25384) from Wiley <img  src="https://licensebuttons.net/l/by-nc/4.0/80x15.png"> (see also the [references](#refs))

# What is Pytim

[Pytim](https://marcello-sega.github.io/pytim/) is a cross-platform python implementation of several methods for the detection of fluid interfaces in molecular simulations. It is based on [`MDAnalysis`](https://www.mdanalysis.org/), but it integrates also seamlessly with `MDTraj`, and can be even used for *online* analysis during an `OpenMM` simulation (see further down for examples [with `MDTraj`](#mdtraj-example) and [with `OpenMM`](#openmm-example)).

So far the following interface/phase identification methods have been implemented:
<img src="https://github.com/Marcello-Sega/pytim/raw/IMAGES/_images/micelle_cut.png" width="380" align="right" style="z-index:999;">


* ITIM
* GITIM 
* SASA
* Willard Chandler
* DBSCAN filtering

## Supported formats
Pytim relies on the [MDAnalysis](http://www.mdanalysis.org/)
package for reading/writing trajectories, and work therefore seamlessly for a number of popular trajectory formats, including:  
* GROMACS
* CHARMM/NAMD
* LAMMPS
* AMBER
* DL_Poly

as well as common structure file formats such as XYZ or PDB (have a look at the [complete list](https://pythonhosted.org/MDAnalysis/documentation_pages/coordinates/init.html#id1))

## Install from PyPi or Anaconda - [![PyPI version](https://badge.fury.io/py/pytim.svg)](https://badge.fury.io/py/pytim) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/pytim/badges/version.svg)](https://anaconda.org/conda-forge/pytim)

PyPi:     ``` pip install --user --upgrade pytim ```

Anaconda: ``` conda install -c conda-forge pytim ```

NOTE: on Mac OS you might want to use ```CFLAGS='-stdlib=libc++' pip install --user --upgrade pytim```


# <a name="example"></a> Show me an example usage, now!

Ok, ok ... have a look below: this example is about computing molecular layers of a flat interface:

### Step 1: interface identification


```python
import MDAnalysis as mda
import pytim
from pytim.datafiles import WATER_GRO

# load the configuration in MDAnalysis
u = mda.Universe(WATER_GRO)

# compute the interface using ITIM. Identify 4 layers.
inter = pytim.ITIM(u,max_layers=4)
```

### That's it. There's no step 2!

Now interfacial atoms are accessible in different ways, pick the one you like:

1. Through the `atoms` group accessible as

```python
inter.atoms.positions # this is a numpy array holding the position of atoms in the layers
```

    array([[ 22.10000038,  16.05999947,  94.19633484],
           [ 22.43999863,  16.97999954,  93.96632385],
           ...,
           [ 33.70999908,  49.02999878,  62.52632904],
           [ 34.06999969,  48.18000031,  61.16632843]], dtype=float32)

2. Using the label that each atom in the `MDAnalysis` universe now has, which specifies in which layer it is found: 

```python
u.atoms.layers  # -1 if not in any layer, 1 if in the first layer, ...
```

3. Using the layers groups, stored as a list (of lists, in case of upper/lower layers in flat interfaces) of groups: 

```pythin
inter.layers

array([[<AtomGroup with 780 atoms>, <AtomGroup with 690 atoms>,
        <AtomGroup with 693 atoms>, <AtomGroup with 660 atoms>],
       [<AtomGroup with 777 atoms>, <AtomGroup with 687 atoms>,
        <AtomGroup with 663 atoms>, <AtomGroup with 654 atoms>]], dtype=object)
```

## Visualisation

Pytim can export in different file formats: the `PDB` format with the `beta` field used to tag the layers, `VTK`, `cube` for both continuous surfaces and particles, and, of course, all formats supported by `MDAnalysis`. 

In [`VMD`](www.ks.uiuc.edu/Research/vmd/), for example, using `beta == 1` allows you to select all atoms in the first interfacial layer. Just save your `PDB` file with layers information using

```python
inter.writepdb('myfile.pdb')
```


In a `jupyter` notebook, you can use `nglview` like this:


```python
import nglview
v = nglview.show_mdanalysis(u)
v.camera='orthographic'
v.center()
system = v.component_0
colors = ['','red','orange','yellow','white']

for n in [1,2,3,4]:
    system.add_spacefill(selection = inter.atoms[inter.atoms.layers==n].indices, color=colors[n] )

system.add_spacefill(selection = (u.atoms - inter.atoms).indices, color='gray' )
```
```python
# this must go in a separate cell
v.display()
```
<p align="center">

<img src="https://github.com/Marcello-Sega/pytim/raw/IMAGES/_images/output_13_0.png" width="60%" align="center" style="z-index:999;">
</p>

## Analysing trajectories (`MDAnalysis` and `mdtraj`)

Once one of the pytim classes (`ITIM`,`GITIM`,`WillardChandler`,...) has been initialised, whenever a new frame is loaded, the interfacial properties will be calculated automatically without need of doing anything else

### MDAnalysis example

```python
import MDAnalysis as mda
import pytim 
from pytim.datafiles import WATER_GRO, WATER_XTC 

u = mda.Universe(WATER_GRO,WATER_XTC)
inter = pytim.ITIM(u)
for step in u.trajectory[:]:
    print "surface atoms:", repr(inter.atoms)
```

### mdtraj example

Under the hood, `pytim` uses `MDAnalysis`, but this is made (almost completely) transparent to the user, so that interoperability with other software is easy to implement. For example, to analyse a trajectory loaded with [`MDTraj`](https://mdtraj.org), it is enough to do the following:

```python
import mdtraj
import pytim                     
from pytim.datafiles import WATER_GRO, WATER_XTC 

t = mdtraj.load_xtc(WATER_XTC,top=WATER_GRO) 
inter = pytim.ITIM(t) 
for step in t[:]:
        print "surface atoms:" , repr(inter.atoms.indices)
```

### openmm example

Another example is using `pytim` to perform *online* interfacial analysis during an [`OpenMM`](https://openmm.org/) simulation:
```python
# openmm imports
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
# pytim
import pytim
from pytim.datafiles import WATER_PDB

# usual openmm setup, we load one of pytim's example files
pdb = PDBFile(WATER_PDB)
forcefield = ForceField('amber99sb.xml', 'spce.xml')
system = forcefield.createSystem(pdb.topology, nonbondedMethod=PME,
        nonbondedCutoff=1*nanometer)
integrator = LangevinIntegrator(300*kelvin, 1/picosecond, 0.002*picoseconds)
simulation = Simulation(pdb.topology, system, integrator)
simulation.context.setPositions(pdb.positions)

# just pass the openmm Simulation object to pytim
inter = pytim.ITIM(simulation)
print repr(inter.atoms)

# the new interfacial atoms will be computed at the end
# of the integration cycle
simulation.step(10)
print repr(inter.atoms)

```



## <a name="non-flat-interfaces"></a> What if the interface is not flat? 

You could use GITIM, or the Willard-Chandler method. 
Let's have a look first at **GITIM**:

```python
import MDAnalysis as mda
import pytim
from   pytim.datafiles import *

u       = mda.Universe(MICELLE_PDB)
g       = u.select_atoms('resname DPC')

interface = pytim.GITIM(u,group=g,molecular=False,
                        symmetry='spherical',alpha=2.5)
layer = interface.layers[0]
interface.writepdb('gitim.pdb',centered=False)
print repr(layer)
<AtomGroup with 872 atoms>
```

`nglview` can be used to show a section cut of the micelle in a `jupyter` notebook:

```python
import nglview
import numpy as np

v = nglview.show_mdanalysis(u)
v.camera='orthographic'
v.center()
v.add_unitcell()
system = v.component_0
system.clear()

selection = g.atoms.positions[:,2]>30.
system.add_spacefill(selection =g.atoms.indices[selection])

selection = np.logical_and(inter.atoms.layers==1,inter.atoms.positions[:,2]>30.)
system.add_spacefill(selection =inter.atoms.indices[selection], color='yellow' )
```

```python
v.display()
```

<p align="center">

<img src="https://github.com/Marcello-Sega/pytim/raw/IMAGES/_images/micelle-gitim.png" width="40%" align="middle">
</p>

The **Willard-Chandler** method can be used, instead to find out isodensity surfaces:

```python
import MDAnalysis as mda
import pytim
from pytim.datafiles import MICELLE_PDB
import nglview

u = mda.Universe(MICELLE_PDB)
g = u.select_atoms('resname DPC')
```

```python
interface = pytim.WillardChandler(u, group=g, mesh=1.5, alpha=3.0)
interface.writecube('data.cube')
```

Done, the density file is written in `.cube` format, we can now open it with 
programs such as [`Paraview`](https://www.paraview.org/), or visualize it in a
jupyter notebook with `nglview`

```python
view = nglview.show_mdanalysis(u.atoms) # the atoms, this will be component_0 in nglview
view.add_component('data.cube') # the density data, this will be component_1 in nglview

view.clear() # looks like this is needed in order for view._display_image() to work correctly 
# let's center the view on our atoms, and draw them as spheres  
view.component_0.center()
view.component_0.add_spacefill(selection='DPC')

# let's add a transparent, red representation for the isodensity surface at 50% density
view.component_1.add_surface(color='red',isolevelType="value",isolevel=0.5,opacity=0.6) 

# add a nice simulation box
view.add_unitcell()
```

```python
view.display()
```

<p align="center">

<img src="https://github.com/Marcello-Sega/pytim/raw/IMAGES/_images/micelle-willard-chandler.png" width="60%" align="middle">
</p>

### Calculate multiple layers with GITIM: solvation shells of glucose
```python
import MDAnalysis as mda
import pytim
from   pytim.datafiles import GLUCOSE_PDB

u       = mda.Universe(GLUCOSE_PDB)
solvent = u.select_atoms('name OW')
glc     = u.atoms - solvent.residues.atoms

inter = pytim.GITIM(u, group=solvent, molecular=True,
                    max_layers=3, alpha=2)

for i in [0,1,2]:
    print "Layer "+str(i),repr(inter.layers[i])
```
```python
Layer 0 <AtomGroup with 81 atoms>
Layer 1 <AtomGroup with 186 atoms>
Layer 2 <AtomGroup with 240 atoms>
```

```python
import nglview
import numpy as np

v = nglview.show_mdanalysis(u)
v.camera='orthographic'
v.center()
v.add_unitcell()

v.clear()

# glucose
v.add_licorice(selection =glc.atoms.indices,radius=.35)

colors = ['yellow','blue','purple']
# hydration layers
for layer in [0,1,2]:
    selection = np.logical_and(inter.atoms.layers==layer+1 ,inter.atoms.positions[:,2]>9)
    v.add_spacefill(selection =inter.atoms.indices[selection], color=colors[layer] )

```
```python
v.display()
```
<p align="center">

<img src="https://github.com/Marcello-Sega/pytim/raw/IMAGES/_images/glc-gitim.png" width="60%" align="middle">
</p>

When calculating surfaces with `GITIM`, it can happen that several disconnected, closed surfaces are found in a simulation box. To restrict the analysis to the largest, clustered interfacial atoms (also when calculating multiple layers), one can pass the `biggest_cluster_only` option, as in:

```python
inter = pytim.GITIM(u, group=solvent, molecular=True, max_layers=3, alpha=2, 
                    biggest_cluster_only=True, cluster_cut = 3.5)
```
In order for this option to have any effect, a `cluster_cut` value should also be passed.

# More info

1. Have a look at the jupyter notebooks: https://github.com/Marcello-Sega/pytim-notebooks

2. Browse the examples in the [Pytim Online Manual](https://marcello-sega.github.io/pytim/quick.html)

3. Check out the Pytim Poster from the 10th Liquid Matter Conference [Available on ResearchGate](http://dx.doi.org/10.13140/RG.2.2.18613.17126)  DOI:10.13140/RG.2.2.18613.17126


# <a name="installation"></a> How to install the package and the documentation? 

## From the PyPI

this will install the latest release present in the Python Package Index:

```
pip install --user --upgrade pytim
```

## From Github
1. Make sure you have an up-to-date version of cython, numpy, scipy and MDAnalysis:

``` 
pip install --user --upgrade cython numpy scipy MDAnalysis
```

2. Download and install pytim

```
git clone https://github.com/Marcello-Sega/pytim.git
cd pytim
python setup.py install --user
```

## Setting the `PYTHONPATH` variable

If you install with the option `--user` (which you have to do if you don't have administrator rights) you shouldn't forget to tell python where to look for the module by setting the `PYTHONPATH` environment variable. 

Under Linux, you could do, for example:
```
export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages
```

Under OS-X, instead, use something like:
```
export PYTHONPATH=$HOME/Library/Python/2.7/lib/python/site-packages
```

You can search for the exact path by issuing the following command:

```
python -c "import site; print(site.USER_SITE)"
```

If this for some reason doesn't work, get some hint using:

```
find $HOME -name site-packages
```


## Trouble installing? 

Some of the most common issues are the following:

**Problem**: The system does not let me write (even using `sudo`) some files

**Solution**: You're most likely running under a recent version of OS-X. Always install packages as user (`pip install <package> --user`

**Problem**: cKDTree complains about the `boxsize` parameter

**Solution**: the version of `scipy` must be >= 0.18


**Problem**: Even though I've upgraded `scipy`, I keep getting problems about `boxsize`

**Solution**: You should tell python where to find packages by setting the variable `$PYTHONPATH` 

**Problem**: some error message mentioning `... file was built for x86_64 which is not the architecture being linked (i386)`

**Solution**: use `export ARCHFLAGS='-arch x86_64'` before installing

**Problem**: I'm getting an annoying message like "UserWarning: Module pytim_dbscan was already imported from [...]"

**Solution**: You've installed pytim, and are launching python within the pytim package directory. Move away from there :)



---------------------------

# References  <img src="https://raw.githubusercontent.com/Marcello-Sega/gitim/ITIM/media/soot1small.png" width="180" align="right" style="z-index:999;"> <a name="refs">

The [pytim paper is avaliable](https://onlinelibrary.wiley.com/doi/epdf/10.1002/jcc.25384)  (under the terms of the Creative Commons BY-NC 4.0 licence) from Wiley. Please cite it if you use pytim for your research:

[M. Sega, S. G. Hantal, B. Fabian and P. Jedlovszky, _J. Comp. Chem._ **39**, 2118-2125 (2018)](http://dx.doi.org/10.1002/jcc.25384) Pytim: A python package for the interfacial analysis of molecular simulations


```
@article{sega2018pytim,
  title={Pytim: A python package for the interfacial analysis of molecular simulations},
  author={Sega, M. and Hantal, G. and F{\'a}bi{\'a}n, B. and Jedlovszky, P.},
  journal={J. Comput. Chem.},
  pages={2118--2125},
  volume={39},
  year={2018},
  publisher={Wiley Online Library}
}
```

Depending on which algorithm you are using, you might also want to cite the following: 

[M. Sega, S. S. Kantorovich, P. Jedlovszky and M. Jorge, _J. Chem. Phys._ **138**, 044110 (2013)](http://dx.doi.org/10.1063/1.4776196) The generalized identification of truly interfacial molecules (ITIM) algorithm for nonplanar interfaces.

[L. B. Pártay, G. Hantal, P. Jedlovszky, Á. Vincze and G. Horvai, _J. Comp. Chem._ **29**, 945 (2008)](http://dx.doi.org/10.1002/jcc.20852) A new method for determining the interfacial molecules and characterizing the surface roughness in computer simulations. Application to the liquid–vapor interface of water

[M. Sega and G. Hantal._Phys. Chem. Chem. Phys._ **29**, 18968-18974 (2017)](https://doi.org/10.1039/C7CP02918G) Phase and interface determination in computer simulations of liquid mixtures with high partial miscibility.

[A. P. Willard, D. Chandler, J. Phys. Chem. B **114**,1954 (2010)](http://dx.doi.org/10.1021/jp909219k) Instantaneous Liquid Interfaces