Welcome to Molecular Dynamics Analysis for IPython (ipyMD)!¶
This package aims to provide a means of producing reusable analysis of Molecular Dynamics (MD) output in the IPython Notebook.
There are many programs for 3D visualisation of MD output (my favourite being Ovito). However, there lacks a means to produce a more thorough, documented analysis of the data. IPython Notebooks are ideal for this type of analysis and so the objective of ipymd is to produce a Python package that can be used in conjuction with programmes like Ovito, to produce documented and reuseable analysis.
The aim of ipymd is to produce IPython Notebooks that include:
- Static images of the simulations
- Analysis of simulation data, including graphical plots
It has been created with the goal to be:
- Easy to use
- Easy to extend
chemlab It builds primarily on the chemlab package, that is an API layer on top of OpenGL. Data is parsed in standard formats, such as [pandas](http://pandas.pydata.org/) dataframes, which are easy to create and use independantly from this package, in order to extend its functionality.
Author | Chris Sewell |
Project Page | https://github.com/chrisjsewell/ipymd |
Contents¶
Quick Start¶
Anaconda is recommended to create a Python environment within which to use ipymd:
conda create -n ipymd -c cjs14 ipymd
source activate ipymd
jupyter notebook
Currently the conda package is only available for OSX. For other operating systems, or to use the latest version from Github, the following environment should work:
conda create -n ipymd python=2.7.11=0 numpy scipy matplotlib pandas ipython ipython-notebook pillow pyopengl pyqt six
If there are any issues, see the known working package dependancies list: https://github.com/chrisjsewell/ipymd/blob/master/working_dependencies_list_osx.txt
User Tutorial¶
In the IPython Notebook, the ipymd package must first be imported:
import ipymd
print ipymd.version()
0.4.2
Basic Atom Creation and Visualisation¶
The input for a basic atomic visualisation, is a pandas Dataframe that specifies the coordinates, size and color of each atom in the following manner:
import pandas as pd
df = pd.DataFrame(
[[2,3,4,1,[0, 0, 255],1],
[1,3,3,1,'orange',1],
[4,3,1,1,'blue',1]],
columns=['x','y','z','radius','color','transparency'])
Distances are measured in Angstroms, and colors can be defined in
[r,g,b] format (0 to 255) or as a string defined in
available_colors
.
print(ipymd.available_colors()['reds'])
['light_salmon', 'salmon', 'dark_salmon', 'light_coral', 'indian_red', 'crimson', 'fire_brick', 'dark_red', 'red']
The Visualise_Sim
class can then be used to setup a visualisation,
which is returned in the form of a PIL
image.
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_atoms(df)
img1 = vis.get_image(size=400,quality=5)
img1

To convert this into an image viewable in IPython, simply parse it to
the visualise
function.
vis.visualise(img1)

Extending this basic procedure, additional objects can be added to the visualisation, the viewpoint can be rotated and multiple images can be output at once, as shown in the following example:
vis.add_axes(length=0.2, offset=(-0.3,0))
vis.add_box([5,0,0],[0,5,0],[0,0,5])
vis.add_plane([[5,0,0],[0,5,2]],alpha=0.3)
vis.add_hexagon([[1,0,0],[0,0,.5]],[0,0,2],color='green')
img_ex1 = vis.get_image(xrot=45, yrot=45)
#img2 = vis.draw_colorlegend(img2,1,2)
vis.visualise([img1,img_ex1])

Atom Creation From Other Sources¶
The ipymd.data_input
module includes a number of classes to automate
the intial creation of the atoms Dataframe, from various sources.
All classes will return a sub-class of DataInput
, that requires the
setup_data
method to be run first, and then the get_atoms
method
returns the atoms Dataframe and the get_meta_data
method returns a
Pandas Series (which includes the vertexes and origin of the simulation
box).
Crystal Parameters¶
This class allows atoms to be created in ordered crystal, as defined by their space group and crystal parameters:
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.4, 5.4, 5.4, 90, 90, 90],
repetitions=[5, 5, 5])
meta = data.get_meta_data()
print meta
atoms_df = data.get_atom_data()
atoms_df.head(2)
origin (0.0, 0.0, 0.0)
a (27.0, 0.0, 0.0)
b (1.65327317885e-15, 27.0, 0.0)
c (1.65327317885e-15, 1.65327317885e-15, 27.0)
dtype: object
id | type | x | y | z | transparency | color | radius | |
---|---|---|---|---|---|---|---|---|
0 | 1 | Na | 0.000000e+00 | 0.0 | 0.0 | 1.0 | light_salmon | 1.0 |
1 | 2 | Na | 3.306546e-16 | 2.7 | 2.7 | 1.0 | light_salmon | 1.0 |
vis2 = ipymd.visualise_sim.Visualise_Sim()
vis2.add_axes()
vis2.add_box(meta.a,meta.b,meta.c, meta.origin)
vis2.add_atoms(atoms_df)
images = [vis2.get_image(xrot=xrot,yrot=45) for xrot in [0,45]]
vis2.visualise(images, columns=2)

A dataframe is available which lists the alternative names for each space group:
df = ipymd.data_input.crystal.get_spacegroup_df()
df.loc[[1,194,225]]
System_type | Point group | Short_name | Full_name | Schoenflies | Fedorov | Shubnikov | Fibrifold | |
---|---|---|---|---|---|---|---|---|
Number | ||||||||
1 | triclinic | 1 | P1 | P 1 | $C_1^1$ | 1s | $(a/b/c)\cdot 1$ | - |
194 | hexagonal | 6/m 2/m 2/m | P63/mmc | P 63/m 2/m 2/c | $D_{6h}^4$ | 88a | $(c:(a/a))\cdot m:6_3\cdot m$ | - |
225 | cubic | 4/m 3 2/m | Fm3m | F 4/m 3 2/m | $O_h^5$ | 73s | $\left ( \frac{a+c}{2}/\frac{b+c}{2}/\frac{a+b... | $2^{-}:2$ |
Crystallographic Information Files¶
.cif files are a common means to store crystallographic data and can be loaded as follows:
cif_path = ipymd.get_data_path('example_crystal.cif')
data = ipymd.data_input.cif.CIF()
data.setup_data(cif_path)
meta = data.get_meta_data()
vis = ipymd.visualise_sim.Visualise_Sim()
vis.basic_vis(data.get_atom_data(), data.get_meta_data(),
xrot=45,yrot=45)

NB: at present, fractional occupancies of lattice sites are returned in the atom Dataframe, but cannot be visualised as such. It is intended that eventually occupancy will be visualised by partial spheres.
data.get_atom_data().head(1)
type | x | y | z | occupancy | transparency | color | radius | |
---|---|---|---|---|---|---|---|---|
0 | Fe | 4.363536 | 2.40065 | 22.642804 | 1.0 | 1.0 | light_salmon | 1.0 |
Lammps Input Data¶
The input data for LAMMPS simulations (supplied to read_data
) can be
input. Note that the get_atom_data
method requires that the
atom_style is defined, in order to define what each data column refers
to.
lammps_path = ipymd.get_data_path('lammps_input.data')
data = ipymd.data_input.lammps.LAMMPS_Input()
data.setup_data(lammps_path,atom_style='charge')
vis = ipymd.visualise_sim.Visualise_Sim()
vis.basic_vis(data.get_atom_data(), data.get_meta_data(),
xrot=45,yrot=45)

Lammps Output Data¶
Output data can be read in the form of a single file or, it is advisable
for efficiency, that a single file is output for each timestep, where
*
is used to define the variable section of the filename. The
get_atoms
and get_simulation_box
methods now take a variable to
define which configuration is returned.
lammps_path = ipymd.get_data_path('atom_onefile.dump')
data = ipymd.data_input.lammps.LAMMPS_Output()
data.setup_data(lammps_path)
print data.count_configs()
vis = ipymd.visualise_sim.Visualise_Sim()
vis.basic_vis(data.get_atom_data(99), data.get_meta_data(99),
spheres=True,xrot=45,yrot=45,quality=5)
99

lammps_path = ipymd.get_data_path(['atom_dump','atoms_*.dump'])
data = ipymd.data_input.lammps.LAMMPS_Output()
data.setup_data(lammps_path)
print data.count_configs()
vis = ipymd.visualise_sim.Visualise_Sim()
vis.basic_vis(data.get_atom_data(99), data.get_meta_data(99),
spheres=False,xrot=90,yrot=0)
99

Atom Manipulation¶
The atoms Dataframe is already very easy to manipulate using the
standard pandas methods. But an
Atom_Manipulation
class has also been created to carry out standard
atom manipulations, such as setting variables dependant on atom type or
altering the geometry, as shown in this example:
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.4, 5.4, 5.4,60,60,60],
repetitions=[5, 5, 5])
meta = data.get_meta_data()
manipulate_atoms = ipymd.atom_manipulation.Atom_Manipulation
new_df = manipulate_atoms(data.get_atom_data(), data.get_meta_data(),undos=2)
new_df.apply_map({'Na':1.5, 'Cl':1},'radius')
new_df.apply_map('color','color',default='grey')
new_df.change_type_variable('Na', 'transparency', 0.5)
new_df.slice_fraction(cmin=0.3, cmax=0.7,update_uc=False)
vis2 = ipymd.visualise_sim.Visualise_Sim()
vis2.add_box(*new_df.meta[['a','b','c','origin']])
vis2.add_axes([meta.a,meta.b,meta.c],offset=(-1.3,-0.7))
vis2.add_atoms(new_df.df, spheres=True)
img1 = vis2.get_image(xrot=45,yrot=45)
vis2.remove_atoms()
new_df.repeat_cell((-1,1),(-1,1),(-1,1))
new_df.color_by_variable('z')
vis2.add_atoms(new_df.df, spheres=True)
vis2.add_box(*new_df.meta[['a','b','c','origin']])
img2 = vis2.get_image(xrot=90,yrot=0)
img3 = ipymd.plotting.create_colormap_image(new_df.df.z.min(), new_df.df.z.max(),
horizontal=True,title='z position',size=150)
vis2.visualise([img1,img2, (280,1), img3], columns=2)

NB: default atom variables (such as color and radii can be set using the
apply_map
method and any column name from those given in
ipymd.shared.atom_data()
:
ipymd.shared.atom_data().head(1)
Num | ARENeg | RCov | RBO | RVdW | MaxBnd | Mass | ElNeg | Ionization | ElAffinity | Name | color_chemlab | color_chemlab_light | color | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Symb | ||||||||||||||
H | 1 | 2.2 | 0.31 | 0.31 | 1.1 | 1 | 1.00794 | 2.2 | 13.5984 | 0.754204 | Hydrogen | white | snow | (191, 191, 191) |
Geometric Analysis¶
Given the simple and flexible form of the atomic data and visualisation,
it is now easier to add more complex geometric analysis. These analyses
are being contained in the atom_analysis
package, and some initial
examples are detailed below. Functions in the
atom_analysis.nearest_neighbour
package are based on the
scipy.spatial.cKDTree
algorithm for identifying nearest neighbours.
Atomic Coordination¶
The two examples below show computation of the coordination of Na, w.r.t Cl, in a simple NaCl crystal (which should be 6). The first does not include a consideration of the repeating boundary conditions, and so outer atoms have a lower coordination number. But the latter computation provides a method which takes this into consideration, by repeating the Cl lattice in each direction before computation.
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.4, 5.4, 5.4, 90, 90, 90],
repetitions=[5, 5, 5])
df = data.get_atom_data()
meta = data.get_meta_data()
df = ipymd.atom_analysis.nearest_neighbour.coordination_bytype(df, 'Na','Cl')
new_df = manipulate_atoms(df,meta)
new_df.filter_variables('Na')
new_df.color_by_variable('coord_Na_Cl',minv=3,maxv=7)
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_axes(offset=(0,-0.3))
vis.add_box(*meta[['a','b','c','origin']])
vis.add_atoms(new_df.df)
img = vis.get_image(xrot=45,yrot=45)
img2 = ipymd.plotting.create_legend_image(new_df.df.coord_Na_Cl,new_df.df.color, title='Na Coordination',size=150,colbytes=True)
vis.visualise([img,img2],columns=2)

data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.4, 5.4, 5.4, 90, 90, 90],
repetitions=[5, 5, 5])
df = data.get_atom_data()
meta = data.get_meta_data()
df = ipymd.atom_analysis.nearest_neighbour.coordination_bytype(
df, 'Na','Cl',repeat_meta=meta)
new_df = manipulate_atoms(df)
new_df.filter_variables('Na')
new_df.color_by_variable('coord_Na_Cl',minv=3,maxv=7)
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_box(*meta[['a','b','c','origin']])
vis.add_axes(offset=(0,-0.3))
vis.add_atoms(new_df.df)
img = vis.get_image(xrot=45,yrot=45)
img2 = ipymd.plotting.create_legend_image(new_df.df.coord_Na_Cl,new_df.df.color, title='Na Coordination',size=150,colbytes=True)
vis.visualise([img,img2],columns=2)

Atomic Structure Comparison¶
compare_to_lattice
takes each atomic coordinate in df1 and computes
the distance to the nearest atom (i.e. lattice site) in df2:
import numpy as np
data1 = ipymd.data_input.crystal.Crystal()
data1.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.4, 5.4, 5.4, 90, 90, 90],
repetitions=[5, 5, 5])
df1 = data1.get_atom_data()
print(('Average distance to nearest atom (identical)',
np.mean(ipymd.atom_analysis.nearest_neighbour.compare_to_lattice(df1,df1))))
data2 = ipymd.data_input.crystal.Crystal()
data2.setup_data(
[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ['Na', 'Cl'],
225, cellpar=[5.41, 5.4, 5.4, 90, 90, 90],
repetitions=[5, 5, 5])
df2 = data2.get_atom_data()
print(('Average distance to nearest atom (different)',
np.mean(ipymd.atom_analysis.nearest_neighbour.compare_to_lattice(df1,df2))))
('Average distance to nearest atom (identical)', 0.0)
('Average distance to nearest atom (different)', 0.022499999999999343)
Common Neighbour Analysis (CNA)¶
CNA (Honeycutt and Andersen, J. Phys. Chem. 91, 4950) is an algorithm to compute a signature for pairs of atoms, which is designed to characterize the local structural environment. Typically, CNA is used as an effective filtering method to classify atoms in crystalline systems (Faken and Jonsson, Comput. Mater. Sci. 2, 279, with the goal to get a precise understanding of which atoms are associated with which phases, and which are associated with defects.
Common signatures for nearest neighbours are:
- FCC = 12 x 4,2,1
- HCP = 6 x 4,2,1 & 6 x 4,2,2
- BCC = 6 x 6,6,6 & 8 x 4,4,4
- Diamond = 12 x 5,4,3 & 4 x 6,6,3
which are tested below:
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.0, 0.0, 0.0]], ['Al'],
225, cellpar=[4.05, 4.05, 4.05, 90, 90, 90],
repetitions=[5, 5, 5])
fcc_meta = data.get_meta_data()
fcc_df = data.get_atom_data()
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0.33333,0.66667,0.25000]], ['Mg'],
194, cellpar=[3.21, 3.21, 5.21, 90, 90, 120],
repetitions=[5,5,5])
hcp_meta = data.get_meta_data()
hcp_df = data.get_atom_data()
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0,0,0]], ['Fe'],
229, cellpar=[2.866, 2.866, 2.866, 90, 90, 90],
repetitions=[5,5,5])
bcc_meta = data.get_meta_data()
bcc_df = data.get_atom_data()
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0,0,0]], ['C'],
227, cellpar=[3.57, 3.57, 3.57, 90, 90, 90],
repetitions=[2,2,2])
diamond_meta = data.get_meta_data()
diamond_df = data.get_atom_data()
print(ipymd.atom_analysis.nearest_neighbour.cna_sum(fcc_df,repeat_meta=fcc_meta))
print(ipymd.atom_analysis.nearest_neighbour.cna_sum(hcp_df,repeat_meta=hcp_meta))
print(ipymd.atom_analysis.nearest_neighbour.cna_sum(bcc_df,repeat_meta=bcc_meta))
print(ipymd.atom_analysis.nearest_neighbour.cna_sum(diamond_df,upper_bound=10,max_neighbours=16,
repeat_meta=diamond_meta))
Counter({'4,2,1': 6000})
Counter({'4,2,2': 1500, '4,2,1': 1500})
Counter({'6,6,6': 2000, '4,4,4': 1500})
Counter({'5,4,3': 768, '6,6,3': 256})
For each atom, the CNA for each nearest-neighbour can be output:
ipymd.atom_analysis.nearest_neighbour.common_neighbour_analysis(hcp_df,repeat_meta=hcp_meta).head(5)
id | type | x | y | z | transparency | color | radius | cna | |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | Mg | -0.000016 | 1.853304 | 1.3025 | 1.0 | light_salmon | 1.0 | {u'4,2,2': 6, u'4,2,1': 6} |
1 | 2 | Mg | 1.605016 | 0.926638 | 3.9075 | 1.0 | light_salmon | 1.0 | {u'4,2,2': 6, u'4,2,1': 6} |
2 | 3 | Mg | -0.000016 | 1.853304 | 6.5125 | 1.0 | light_salmon | 1.0 | {u'4,2,2': 6, u'4,2,1': 6} |
3 | 4 | Mg | 1.605016 | 0.926638 | 9.1175 | 1.0 | light_salmon | 1.0 | {u'4,2,2': 6, u'4,2,1': 6} |
4 | 5 | Mg | -0.000016 | 1.853304 | 11.7225 | 1.0 | light_salmon | 1.0 | {u'4,2,2': 6, u'4,2,1': 6} |
This can be used to produce a plot identifying likely structure of an unknown structure:
lammps_path = ipymd.get_data_path('thermalized_troilite.dump')
data = ipymd.data_input.lammps.LAMMPS_Output()
data.setup_data(lammps_path)
df = data.get_atom_data()
df = df[df.type==1]
plot = ipymd.atom_analysis.nearest_neighbour.cna_plot(df,repeat_meta=data.get_meta_data())
plot.display_plot()

A visualisation of the probable local character of each atom can also be
created. Note the accuracy parameter in the cna_categories
method
allows for more robust fitting to the ideal signatures:
lammps_path = ipymd.get_data_path('thermalized_troilite.dump')
data = ipymd.data_input.lammps.LAMMPS_Output()
data.setup_data(lammps_path)
df = data.get_atom_data()
meta = data.get_meta_data()
df = df[df.type==1]
df = ipymd.atom_analysis.nearest_neighbour.cna_categories(
df,repeat_meta=meta,accuracy=0.7)
manip = ipymd.atom_manipulation.Atom_Manipulation(df)
manip.color_by_categories('cna')
#manip.apply_colormap({'Other':'blue','FCC':'green','HCP':'red'}, type_col='cna')
manip.change_type_variable('Other','transparency',0.5,type_col='cna')
atom_df = manip.df
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_box(*meta[['a','b','c','origin']])
vis.add_atoms(atom_df)
img = vis.get_image(xrot=90)
img2 = ipymd.plotting.create_legend_image(atom_df.cna,atom_df.color,
title='CNA Category\nof Fe Sublattice',size=150,colbytes=True)
vis.visualise([img,img2],columns=2)

Vacany Identification¶
The vacancy_identification
method finds grid sites with no atoms
within a specified distance:
cif_path = ipymd.get_data_path('pyr_4C_monoclinic.cif')
data = ipymd.data_input.cif.CIF()
data.setup_data(cif_path)
cif4c_df, cif4c_meta = data.get_atom_data(), data.get_meta_data()
vac_df = ipymd.atom_analysis.nearest_neighbour.vacancy_identification(cif4c_df,0.2,2.3,cif4c_meta,
radius=2.3,remove_dups=True)
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_atoms(vac_df)
vis.add_box(*cif4c_meta[['a','b','c','origin']])
vis.add_atoms(cif4c_df)
vis.visualise([vis.get_image(xrot=90,yrot=10),
vis.get_image(xrot=45,yrot=45)],columns=2)

XRD Spectrum Prediction¶
This is an implementation of the virtual x-ray diffraction pattern algorithm, from http://http://dx.doi.org/10.1007/s11837-013-0829-3.
data = ipymd.data_input.crystal.Crystal()
data.setup_data(
[[0,0,0]], ['Fe'],
229, cellpar=[2.866, 2.866, 2.866, 90, 90, 90],
repetitions=[5,5,5])
meta = data.get_meta_data()
atoms_df = data.get_atom_data()
wlambda = 1.542 # Angstrom (Cu K-alpha)
thetas, Is = ipymd.atom_analysis.spectral.compute_xrd(atoms_df,meta,wlambda)
plot = ipymd.atom_analysis.spectral.plot_xrd_hist(thetas,Is,wlambda=wlambda,barwidth=1)
plot.axes.set_xlim(20,90)
plot.display_plot(True)

The predicted spectrum peaks (for alpha-Fe) shows good correlation with experimentally derived data:
from IPython.display import Image
exp_path = ipymd.get_data_path('xrd_fe_bcc_Cu_kalpha.png',
module=ipymd.atom_analysis)
Image(exp_path,width=380)

System Analysis¶
Within the LAMMPS_Output
class there is also the option to read in a
systems data file, with a log of global variables for each simulation
timestep.
data = ipymd.data_input.lammps.LAMMPS_Output()
sys_path = ipymd.get_data_path('system.dump')
data.setup_data(sys_path=sys_path)
sys_data = data.get_meta_data_all()
sys_data.head()
time | natoms | a | b | vol | press | temp | peng | keng | teng | enth | |
---|---|---|---|---|---|---|---|---|---|---|---|
config | |||||||||||
2 | 200 | 5880 | 3.997601 | 3.997601 | 106784.302378 | 2568.163297 | 6.616167 | -576911.132565 | 115.942920 | -576795.189644 | -572795.687453 |
3 | 400 | 5880 | 3.993996 | 3.993997 | 106591.809864 | 1560.503603 | 8.739034 | -576962.187377 | 153.144425 | -576809.042952 | -574383.189834 |
4 | 600 | 5880 | 3.989881 | 3.989882 | 106372.285789 | 364.540620 | 8.262727 | -576965.242403 | 144.797535 | -576820.444868 | -576254.921821 |
5 | 800 | 5880 | 3.986465 | 3.986465 | 106190.203677 | -586.959616 | 7.597382 | -576960.911674 | 133.137903 | -576827.773772 | -577736.783571 |
6 | 1000 | 5880 | 3.988207 | 3.988208 | 106283.055838 | 128.391396 | 4.990469 | -576921.379605 | 87.453896 | -576833.925708 | -576634.915276 |
ax = sys_data.plot('time','temp',legend=False)
ax.set_xlabel('Time (fs)')
ax.set_ylabel('Temperature (K)');
ax.grid()

Plotting¶
Plotting is handled by the Plotter
class, which is mainly a useful
wrapper around matplotlib
.
df = pd.DataFrame(
[[2,3,4,1,[0, 0, 255],1],
[1,3,3,1,'orange',1],
[4,3,1,1,'blue',1]],
columns=['x','y','z','radius','color','transparency'])
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_atoms(df)
vis.add_axes(length=0.2, offset=(-0.3,0))
vis.add_box([5,0,0],[0,5,0],[0,0,5])
vis.add_plane([[5,0,0],[0,5,2]],alpha=0.3)
vis.add_hexagon([[1,0,0],[0,0,.5]],[0,0,2],color='green')
img_ex1 = vis.get_image(xrot=45, yrot=45)
with ipymd.plotting.style('xkcd'):
plot = ipymd.plotting.Plotter(figsize=(5,3))
plot.axes.scatter([0,0.5,1.2],[0,0.5,1],s=30)
plot.axes.set_xlabel('some variable')
plot.axes.set_ylabel('some other variable')
plot.add_image_annotation(img_ex1,(230,100),(0.5,0.5),zoom=0.5)
plot.display_plot(tight_layout=True)

Matplotlib also has an animation capability:
import numpy as np
x_iter = [np.linspace(0, 2, 1000) for i in range(100)]
def y_iter(x_iter):
for i,x in enumerate(x_iter):
yield np.sin(2 * np.pi * (x - 0.01 * i))
with ipymd.plotting.style('ggplot'):
line_anim = ipymd.plotting.animation_line(x_iter,y_iter(x_iter),
xlim=(0,2),ylim=(-2,2),incl_controls=False)
line_anim
Recent IPython Notebook version have brought powerful new interactive features, such as Javascript widgets:
One could imagine using this feature to overlay time-dependant field information on to 2D visualiations of atomic configurations:
# visualise atoms
df = pd.DataFrame(
[[2,3,4,1,'gray',0.6],
[1,3,3,1,'gray',0.6],
[4,3,1,1,'gray',0.6]],
columns=['x','y','z','radius','color','transparency'])
vis = ipymd.visualise_sim.Visualise_Sim()
vis.add_atoms(df,illustrate=True)
img1 = vis.get_image(size=400,quality=5,xrot=90)
plot = ipymd.plotting.Plotter()
plot.add_image(img1,width=2,height=2,origin=(-1,-1))
# setup contour iterators
import numpy as np
from itertools import izip
from matplotlib.mlab import bivariate_normal
x_iter = [np.linspace(-1, 1, 1000) for i in range(100)]
y_iter = [np.linspace(-1, 1, 1000) for i in range(100)]
def z_iter(x_iter,y_iter):
for i,(x,y) in enumerate(izip(x_iter,y_iter)):
X, Y = np.meshgrid(x, y)
yield bivariate_normal(X, Y, 0.005*(i+1), 0.005*(i+1),0.5,0.5)
# create contour visualisation
with ipymd.plotting.style('ggplot'):
c_anim = ipymd.plotting.animation_contourf(x_iter,y_iter,z_iter(x_iter,y_iter),
xlim=(-1,1),ylim=(-1,1),
cmap='PuBu_r',alpha=0.5,plot=plot)
c_anim
Package API¶
ipymd package¶
Subpackages¶
ipymd.atom_analysis package¶
Created on Thu Jul 14 14:06:40 2016
@author: cjs14
functions to calculate basic properties of the atoms
-
ipymd.atom_analysis.basic.
density_bb
(atoms_df, vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]])[source]¶ calculate density of the bounding box (assuming all atoms are inside)
-
ipymd.atom_analysis.basic.
lattparams_bb
(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], rounded=None, cells=(1, 1, 1))[source]¶ calculate unit cell parameters of the bounding box
- rounded : int
- the number of decimal places to return
- cells : (int,int,int)
- how many unit cells the vectors represent in each direction
Returns: Return type: a, b, c, alpha, beta, gamma (in degrees)
-
ipymd.atom_analysis.basic.
volume_bb
(vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], rounded=None, cells=(1, 1, 1))[source]¶ calculate volume of the bounding box
- rounded : int
- the number of decimal places to return
- cells : (int,int,int)
- how many unit cells the vectors represent in each direction
Returns: volume Return type: float
Created on Thu Jul 14 14:05:09 2016
@author: cjs14
functions based on nearest neighbour calculations
-
ipymd.atom_analysis.nearest_neighbour.
bond_lengths
(atoms_df, coord_type, lattice_type, max_dist=4, max_coord=16, repeat_meta=None, rounded=2, min_dist=0.01, leafsize=100)[source]¶ calculate the unique bond lengths atoms in coords_atoms, w.r.t lattice_atoms
- atoms_df : pandas.Dataframe
- all atoms
- coord_type : string
- atoms to calcualte coordination of
- lattice_type : string
- atoms to act as lattice for coordination
- max_dist : float
- maximum distance for coordination consideration
- max_coord : float
- maximum possible coordination number
- repeat_meta : pandas.Series
- include consideration of repeating boundary idenfined by a,b,c in the meta data
- min_dist : float
- lattice points within this distance of the atom will be ignored (assumed self-interaction)
- leafsize : int
- points at which the algorithm switches to brute-force (kdtree specific)
Returns: distances – list of unique distances Return type: set
-
ipymd.atom_analysis.nearest_neighbour.
cna_categories
(atoms_df, accuracy=1.0, upper_bound=4, max_neighbours=24, repeat_meta=None, leafsize=100, ipython_progress=False)[source]¶ compute summed atomic environments of each atom in atoms_df
Based on Faken, Daniel and Jónsson, Hannes, ‘Systematic analysis of local atomic structure combined with 3D computer graphics’, March 1994, DOI: 10.1016/0927-0256(94)90109-0
signatures: - FCC = 12 x 4,2,1 - HCP = 6 x 4,2,1 & 6 x 4,2,2 - BCC = 6 x 6,6,6 & 8 x 4,4,4 - Diamond = 12 x 5,4,3 & 4 x 6,6,3 - Icosahedral = 12 x 5,5,5
Parameters: - accuracy (float) – 0 to 1 how accurate to fit to signature
- repeat_meta (pandas.Series) – include consideration of repeating boundary idenfined by a,b,c in the meta data
- ipython_progress (bool) – print progress to IPython Notebook
Returns: df – copy of atoms_df with new column named cna
Return type: pandas.Dataframe
-
ipymd.atom_analysis.nearest_neighbour.
cna_plot
(atoms_df, upper_bound=4, max_neighbours=24, repeat_meta=None, leafsize=100, barwidth=1, ipython_progress=False)[source]¶ compute summed atomic environments of each atom in atoms_df
Based on Faken, Daniel and Jónsson, Hannes, ‘Systematic analysis of local atomic structure combined with 3D computer graphics’, March 1994, DOI: 10.1016/0927-0256(94)90109-0
common signatures: - FCC = 12 x 4,2,1 - HCP = 6 x 4,2,1 & 6 x 4,2,2 - BCC = 6 x 6,6,6 & 8 x 4,4,4 - Diamond = 12 x 5,4,3 & 4 x 6,6,3 - Icosahedral = 12 x 5,5,5
Parameters: - repeat_meta (pandas.Series) – include consideration of repeating boundary idenfined by a,b,c in the meta data
- ipython_progress (bool) – print progress to IPython Notebook
Returns: plot – a matplotlib plot
Return type:
-
ipymd.atom_analysis.nearest_neighbour.
cna_sum
(atoms_df, upper_bound=4, max_neighbours=24, repeat_meta=None, leafsize=100, ipython_progress=False)[source]¶ compute summed atomic environments of each atom in atoms_df
Based on Faken, Daniel and Jónsson, Hannes, ‘Systematic analysis of local atomic structure combined with 3D computer graphics’, March 1994, DOI: 10.1016/0927-0256(94)90109-0
common signatures: - FCC = 12 x 4,2,1 - HCP = 6 x 4,2,1 & 6 x 4,2,2 - BCC = 6 x 6,6,6 & 8 x 4,4,4 - Diamond = 12 x 5,4,3 & 4 x 6,6,3 - Icosahedral = 12 x 5,5,5
Parameters: - repeat_meta (pandas.Series) – include consideration of repeating boundary idenfined by a,b,c in the meta data
- ipython_progress (bool) – print progress to IPython Notebook
Returns: counter – a counter of cna signatures
Return type: Counter
-
ipymd.atom_analysis.nearest_neighbour.
common_neighbour_analysis
(atoms_df, upper_bound=4, max_neighbours=24, repeat_meta=None, leafsize=100, ipython_progress=False)[source]¶ compute atomic environment of each atom in atoms_df
Based on Faken, Daniel and Jónsson, Hannes, ‘Systematic analysis of local atomic structure combined with 3D computer graphics’, March 1994, DOI: 10.1016/0927-0256(94)90109-0
ideally: - FCC = 12 x 4,2,1 - HCP = 6 x 4,2,1 & 6 x 4,2,2 - BCC = 6 x 6,6,6 & 8 x 4,4,4 - icosahedral = 12 x 5,5,5
- repeat_meta : pandas.Series
- include consideration of repeating boundary idenfined by a,b,c in the meta data
- ipython_progress : bool
- print progress to IPython Notebook
Returns: df – copy of atoms_df with new column named cna Return type: pandas.Dataframe
-
ipymd.atom_analysis.nearest_neighbour.
compare_to_lattice
(atoms_df, lattice_atoms_df, max_dist=10, leafsize=100)[source]¶ calculate the minimum distance of each atom in atoms_df from a lattice point in lattice_atoms_df
- atoms_df : pandas.Dataframe
- atoms to calculate for
- lattice_atoms_df : pandas.Dataframe
- atoms to act as lattice points
- max_dist : float
- maximum distance for consideration in computation
- leafsize : int
- points at which the algorithm switches to brute-force (kdtree specific)
Returns: distances – list of distances to nearest atom in lattice Return type: list
-
ipymd.atom_analysis.nearest_neighbour.
coordination
(coord_atoms_df, lattice_atoms_df, max_dist=4, max_coord=16, repeat_meta=None, min_dist=0.01, leafsize=100)[source]¶ calculate the coordination number of each atom in coords_atoms, w.r.t lattice_atoms
- coords_atoms_df : pandas.Dataframe
- atoms to calcualte coordination of
- lattice_atoms_df : pandas.Dataframe
- atoms to act as lattice for coordination
- max_dist : float
- maximum distance for coordination consideration
- max_coord : float
- maximum possible coordination number
- repeat_meta : pandas.Series
- include consideration of repeating boundary idenfined by a,b,c in the meta data
- min_dist : float
- lattice points within this distance of the atom will be ignored (assumed self-interaction)
- leafsize : int
- points at which the algorithm switches to brute-force (kdtree specific)
Returns: coords – list of coordination numbers Return type: list
-
ipymd.atom_analysis.nearest_neighbour.
coordination_bytype
(atoms_df, coord_type, lattice_type, max_dist=4, max_coord=16, repeat_meta=None, min_dist=0.01, leafsize=100)[source]¶ returns dataframe with additional column for the coordination number of each atom of coord type, w.r.t lattice_type atoms
effectively an extension of calc_df_coordination
- atoms_df : pandas.Dataframe
- all atoms
- coord_type : string
- atoms to calcualte coordination of
- lattice_type : string
- atoms to act as lattice for coordination
- max_dist : float
- maximum distance for coordination consideration
- max_coord : float
- maximum possible coordination number
- repeat_meta : pandas.Series
- include consideration of repeating boundary idenfined by a,b,c in the meta data
- min_dist : float
- lattice points within this distance of the atom will be ignored (assumed self-interaction)
- leafsize : int
- points at which the algorithm switches to brute-force (kdtree specific)
Returns: df – copy of atoms_df with new column named coord_{coord_type}_{lattice_type} Return type: pandas.Dataframe
-
ipymd.atom_analysis.nearest_neighbour.
guess_bonds
(atoms_df, covalent_radii=None, threshold=0.1, max_length=5.0, radius=0.1, transparency=1.0, color=None)[source]¶ guess bonds between atoms, based on approximate covalent radii
Parameters: - atoms_df (pandas.Dataframe) – all atoms, requires colums [‘x’,’y’,’z’,’type’, ‘color’]
- covalent_radii (dict or None) – a dict of covalent radii for each atom type, if None then taken from ipymd.shared.atom_data
- threshold (float) – include bonds with distance +/- threshold of guessed bond length (Angstrom)
- max_length (float) – maximum bond length to include (Angstrom)
- radius (float) – radius of displayed bond cylinder (Angstrom)
- transparency (float) – transparency of displayed bond cylinder
- color (str or tuple) – color of displayed bond cylinder, if None then colored by atom color
Returns: bonds_df – a dataframe with start/end indexes relating to atoms in atoms_df
Return type: pandas.Dataframe
-
ipymd.atom_analysis.nearest_neighbour.
vacancy_identification
(atoms_df, res=0.2, nn_dist=2.0, repeat_meta=None, remove_dups=True, color='red', transparency=1.0, radius=1, type_name='Vac', leafsize=100, n_jobs=1, ipython_progress=False)[source]¶ identify vacancies
- atoms_df : pandas.Dataframe
- atoms to calculate for
- res : float
- resolution of vacancy identification, i.e. spacing of reference lattice
- nn_dist : float
- maximum nearest-neighbour distance considered as a vacancy
- repeat_meta : pandas.Series
- include consideration of repeating boundary idenfined by a,b,c in the meta data
- remove_dups : bool
- only keep one vacancy site within the nearest-neighbour distance
- leafsize : int
- points at which the algorithm switches to brute-force (kdtree specific)
- n_jobs : int, optional
- Number of jobs to schedule for parallel processing. If -1 is given all processors are used.
- ipython_progress : bool
- print progress to IPython Notebook
Returns: vac_df – new atom dataframe of vacancy sites as atoms Return type: pandas.DataFrame
Created on Tue Jul 12 20:18:04 2016
Derived from: LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator http://lammps.sandia.gov, Sandia National Laboratories Steve Plimpton, sjplimp@sandia.gov Copyright (2003) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. This software is distributed under the GNU General Public License. https://github.com/lammps/lammps/tree/lammps-icms/src/USER-DIFFRACTION
This package contains the commands neeed to calculate x-ray and electron diffraction intensities based on kinematic diffraction theory. Detailed discription of the computation can be found in the following works:
Coleman, S.P., Spearot, D.E., Capolungo, L. (2013) Virtual diffraction analysis of Ni [010] symmetric tilt grain boundaries, Modelling and Simulation in Materials Science and Engineering, 21 055020. doi:10.1088/0965-0393/21/5/055020
Coleman, S.P., Sichani, M.M., Spearot, D.E. (2014) A computational algorithm to produce virtual x-ray and electron diffraction patterns from atomistic simulations, JOM, 66 (3), 408-416. doi:10.1007/s11837-013-0829-3
Coleman, S.P., Pamidighantam, S. Van Moer, M., Wang, Y., Koesterke, L. Spearot D.E (2014) Performance improvement and workflow development of virtual diffraction calculations, XSEDE14, doi:10.1145/2616498.2616552
@author: chris sewell
-
ipymd.atom_analysis.spectral.
xrd_compute
(atoms_df, meta_data, wlambda, min2theta=1.0, max2theta=179.0, lp=True, rspace=[1, 1, 1], manual=False, periodic=[True, True, True])[source]¶ Compute predicted x-ray diffraction intensities for a given wavelength
- atoms_df : pandas.DataFrame
- a dataframe of info for each atom, including columns; x,y,z,type
- meta_data : pandas.Series
- data of a,b,c crystal vectors (as tuples, e.g. meta_data.a = (0,0,1))
- wlambda : float
- radiation wavelength (length units) typical values are Cu Ka = 1.54, Mo Ka = 0.71 Angstroms
- min2theta : float
- minimum 2 theta range to explore (degrees)
- max2theta : float
- maximum 2 theta range to explore (degrees)
- lp : bool
- switch to apply Lorentz-polarization factor
- use_triclinic : bool
- use_triclinic
- rspace : list of floats
- parameters to adjust the spacing of the reciprocal lattice nodes in the h, k, and l directions respectively
- manual : bool
- use manual spacing of reciprocal lattice points based on the values of the c parameters (good for comparing diffraction results from multiple simulations, but small c required).
- periodic : list of bools
- whether periodic boundary in the h, k, and l directions respectively
Returns: df – theta (in degrees), I, h, k and l for each k-point Return type: pandas.DataFrame Notes
This is an implementation of the virtual x-ray diffraction pattern algorithm by Coleman et al. [ref1]
The algorithm proceeds in the following manner:
- Define a crystal structure by position (x,y,z) and atom/ion type.
- Define the x-ray wavelength to use
- Compute the full reciprocal lattice mesh
- Filter reciprocal lattice points by those in the Eswald’s sphere
- Compute the structure factor at each reciprocal lattice point, for each atom type
- Compute the x-ray diffraction intensity at each reciprocal lattice point
- Group and sum intensities by angle
reciprocal points of the lattice are computed such that:
\[\mathbf{K} = {m_{1}}\cdot \mathbf{b}_{1}+{m_{2}}\cdot \mathbf{b}_{2}+{m_{3}}\cdot \mathbf{b}_{3}\]where,
\[\begin{split}\begin{aligned} \mathbf {b_{1}} &= {\frac {\mathbf {a_{2}} \times \mathbf {a_{3}} }{\mathbf {a_{1}} \cdot (\mathbf {a_{2}} \times \mathbf {a_{3}} )}}\\ \mathbf {b_{2}} &= {\frac {\mathbf {a_{3}} \times \mathbf {a_{1}} }{\mathbf {a_{2}} \cdot (\mathbf {a_{3}} \times \mathbf {a_{1}} )}}\\ \mathbf {b_{3}} &= {\frac {\mathbf {a_{1}} \times \mathbf {a_{2}} }{\mathbf {a_{3}} \cdot (\mathbf {a_{1}} \times \mathbf {a_{2}} )}} \end{aligned}\end{split}\]The reciprocal k-point modulii of the x-ray is calculated from Bragg’s law:
\[\left| {\mathbf{K}_{\lambda}} \right| = \frac{1}{{d_{\text{hkl}} }} = \frac{2\sin \left( \theta \right)}{\lambda }\]This is used to construct an Eswald’s sphere, and only reciprocal lattice ponts within are retained, as illustrated:
The atomic scattering factors, fj, accounts for the reduction in diffraction intensity due to Compton scattering, with coefficients based on the electron density around the atomic nuclei.
\[f_j \left(\frac{\sin \theta}{\lambda}\right) = \left[ \sum\limits^4_i a_i \exp \left( -b_i \frac{\sin^2 \theta}{\lambda^2} \right)\right] + c = \left[ \sum\limits^4_i a_i \exp \left( -b_i \left(\frac{\left| {\mathbf{K}} \right|}{2}\right)^2 \right)\right] + c\]The relative diffraction intensity from x-rays is computed at each reciprocal lattice point through:
\[I_x(\mathbf{K}) = Lp(\theta) \frac{F(\mathbf{K})F^*(\mathbf{K})}{N}\]such that:
\[F ({\mathbf{K}} )= \sum\limits_{j = 1}^{N} {f_{j}.e^{\left( {2\pi i \, {\mathbf{K}} \cdot {\mathbf{r}}_{j} } \right)}} = \sum\limits_{j = 1}^{N} {f_j.\left[ \cos \left( 2\pi \mathbf{K} \cdot \mathbf{r}_j \right) + i \sin \left( 2\pi \mathbf{K} \cdot \mathbf{r}_j \right) \right]}\]and the Lorentz-polarization factor is:
\[Lp(\theta) = \frac{1+\cos^2 (2\theta)}{\cos(\theta)\sin^2(\theta)}\]References
[ref1] 1.Coleman, S. P., Sichani, M. M. & Spearot, D. E. A Computational Algorithm to Produce Virtual X-ray and Electron Diffraction Patterns from Atomistic Simulations. JOM 66, 408–416 (2014).
-
ipymd.atom_analysis.spectral.
xrd_group_i
(df, tstep=None, sym_equiv_hkl='none')[source]¶ group xrd intensities by theta
Parameters: - df (pandas.DataFrame) – containing columns; [‘theta’,’I’] and optional [‘h’,’k’,’l’]
- tstep (None or float) – if not None, group thetas within ranges i to i+tstep
- sym_equiv_hkl (str) – group hkl by symmetry-equivalent refelections; [‘none’,’mmm’,’m-3m’]
Returns: df
Return type: Notes
if grouping by theta step, then the theta value for each group will be the intensity weighted average
Crystal System | Laue Class | Symmetry-Equivalent Reflections | Multiplicity ————– | ———- | ——————————- | ———— Triclinic | -1 | hkl ≡ -h-k-l | 2 Monoclinic | 2/m | hkl ≡ -hk-l ≡ -h-k-l ≡ h-kl | 4 Orthorhombic | mmm | hkl ≡ h-k-l ≡ -hk-l ≡ -h-kl ≡ -h-k-l ≡ -hkl ≡ h-kl ≡ hk-l | 8 Tetragonal | 4/m | hkl ≡ -khl ≡ -h-kl ≡ k-hl ≡ -h-k-l ≡ k-h-l ≡ hk-l ≡ -kh-l | 8
4/mmm | hkl ≡ -khl ≡ -h-kl ≡ k-hl ≡ -h-k-l ≡ k-h-l ≡ hk-l ≡ -kh-l || ≡ khl ≡ -hkl ≡ -k-hl ≡ h-kl ≡ -k-h-l ≡ h-k-l ≡ kh-l ≡ -hk-l | 16- Cubic | m-3 | hkl ≡ -hkl ≡ h-kl ≡ hk-l ≡ -h-k-l ≡ h-k-l ≡ -hk-l ≡ -h-kl |
- | ≡ klh ≡ -klh ≡ k-lh ≡ kl-h ≡ -k-l-h ≡ k-l-h ≡ -kl-h ≡ -k-lh || ≡ lhk ≡ -lhk ≡ l-hk ≡ lh-k ≡ -l-h-k ≡ l-h-k ≡ -lh-k ≡ -l-hk | 24m-3m | hkl ≡ -hkl ≡ h-kl ≡ hk-l ≡ -h-k-l ≡ h-k-l ≡ -hk-l ≡ -h-kl || ≡ klh ≡ -klh ≡ k-lh ≡ kl-h ≡ -k-l-h ≡ k-l-h ≡ -kl-h ≡ -k-lh || ≡ lhk ≡ -lhk ≡ l-hk ≡ lh-k ≡ -l-h-k ≡ l-h-k ≡ -lh-k ≡ -l-hk || ≡ khl ≡ -khl ≡ k-hl ≡ kh-l ≡ -k-h-l ≡ k-h-l ≡ -kh-l ≡ -k-hl || ≡ lkh ≡ -lkh ≡ l-kh ≡ lk-h ≡ -l-k-h ≡ l-k-h ≡ -lk-h ≡ -l-kh || ≡ hlk ≡ -hlk ≡ h-lk ≡ hl-k ≡ -h-l-k ≡ h-l-k ≡ -hl-k ≡ -h-lk | 48
-
ipymd.atom_analysis.spectral.
xrd_plot
(df, icol='I_norm', imin=0.01, barwidth=1.0, hkl_num=0, hkl_trange=[0.0, 180.0], incl_multi=False, label_inline=True, label_trange=[0.0, 180.0], ax=None, **kwargs)[source]¶ create plot of xrd pattern
- df : pd.DataFrame
- containing columns [‘theta’,icol] and optional [‘hkl’,’multiplicity’]
- icol : str
- column name for intensity data
- imin : float
- minimum intensity to display
- barwidth : float or None
- if None then the barwidth will be the bin width
- hkl_num : int
- number of k-point values to label
- hkl_trange : [float,float]
- theta range within which to label peaks with k-point values
- label_inline : bool
- place k-point labels inline or at top of plot
- label_trange : [float,float]
- if not inline, theta range within which to fit k-point labels
- incl_multi : bool
- add multiplicity to k-point label
- kwargs : optional
- additional arguments for bar plot (e.g. label, color, alpha)
Returns: plot – a plot object Return type: ipymd.plotting.Plotting
ipymd.data_input package¶
-
ipymd.data_input.spacegroup.cell.
cell_to_cellpar
(cell)[source]¶ Returns the cell parameters [a, b, c, alpha, beta, gamma] as a numpy array.
-
ipymd.data_input.spacegroup.cell.
cellpar_to_cell
(cellpar, ab_normal=(0, 0, 1), a_direction=None)[source]¶ Return a 3x3 cell matrix from cellpar = [a, b, c, alpha, beta, gamma]. The returned cell is orientated such that a and b are normal to ab_normal and a is parallel to the projection of a_direction in the a-b plane.
Default a_direction is (1,0,0), unless this is parallel to ab_normal, in which case default a_direction is (0,0,1).
The returned cell has the vectors va, vb and vc along the rows. The cell will be oriented such that va and vb are normal to ab_normal and va will be along the projection of a_direction onto the a-b plane.
Example:
>>> cell = cellpar_to_cell([1, 2, 4, 10, 20, 30], (0,1,1), (1,2,3)) >>> np.round(cell, 3) array([[ 0.816, -0.408, 0.408], [ 1.992, -0.13 , 0.13 ], [ 3.859, -0.745, 0.745]])
Definition of the Spacegroup class.
This module only depends on NumPy and the space group database.
-
class
ipymd.data_input.spacegroup.spacegroup.
Spacegroup
(spacegroup, setting=1, datafile=None)[source]¶ Bases:
object
Returns a new Spacegroup instance.
Parameters:
- spacegroup : int | string | Spacegroup instance
- The space group number in International Tables of Crystallography or its Hermann-Mauguin symbol. E.g. spacegroup=225 and spacegroup=’F m -3 m’ are equivalent.
- setting : 1 | 2
- Some space groups have more than one setting. setting determines Which of these should be used.
- datafile : None | string
- Path to database file. If None, the the default database will be used.
-
__eq__
(other)[source]¶ Chech whether self and other refer to the same spacegroup number and setting.
-
__str__
()[source]¶ Return a string representation of the space group data in the same format as found the database.
-
centrosymmetric
¶ Whether a center of symmetry exists.
-
equivalent_reflections
(hkl)[source]¶ Return all equivalent reflections to the list of Miller indices in hkl.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.equivalent_reflections([[0, 0, 2]]) array([[ 0, 0, -2], [ 0, -2, 0], [-2, 0, 0], [ 2, 0, 0], [ 0, 2, 0], [ 0, 0, 2]])
-
equivalent_sites
(scaled_positions, ondublicates='error', symprec=0.001)[source]¶ Returns the scaled positions and all their equivalent sites.
Parameters:
- scaled_positions: list | array
- List of non-equivalent sites given in unit cell coordinates.
- ondublicates : ‘keep’ | ‘replace’ | ‘warn’ | ‘error’
Action if scaled_positions contain symmetry-equivalent positions:
- ‘keep’
- ignore additional symmetry-equivalent positions
- ‘replace’
- replace
- ‘warn’
- like ‘keep’, but issue an UserWarning
- ‘error’
- raises a SpacegroupValueError
- symprec: float
- Minimum “distance” betweed two sites in scaled coordinates before they are counted as the same site.
Returns:
- sites: array
- A NumPy array of equivalent sites.
- kinds: list
- A list of integer indices specifying which input site is equivalent to the corresponding returned site.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sites, kinds = sg.equivalent_sites([[0, 0, 0], [0.5, 0.0, 0.0]]) >>> sites array([[ 0. , 0. , 0. ], [ 0. , 0.5, 0.5], [ 0.5, 0. , 0.5], [ 0.5, 0.5, 0. ], [ 0.5, 0. , 0. ], [ 0. , 0.5, 0. ], [ 0. , 0. , 0.5], [ 0.5, 0.5, 0.5]]) >>> kinds [0, 0, 0, 0, 1, 1, 1, 1]
-
get_op
()[source]¶ Returns all symmetry operations (including inversions and subtranslations), but unlike get_symop(), they are returned as two ndarrays.
-
get_symop
()[source]¶ Returns all symmetry operations (including inversions and subtranslations) as a sequence of (rotation, translation) tuples.
-
lattice
¶ Lattice type: P primitive I body centering, h+k+l=2n F face centering, h,k,l all odd or even A,B,C single face centering, k+l=2n, h+l=2n, h+k=2n R rhombohedral centering, -h+k+l=3n (obverse); h-k+l=3n (reverse)
-
no
¶ Space group number in International Tables of Crystallography.
-
nsubtrans
¶ Number of cell-subtranslation vectors.
-
nsymop
¶ Total number of symmetry operations.
-
reciprocal_cell
¶ Tree Miller indices that span all kinematically non-forbidden reflections as a matrix with the Miller indices along the rows.
-
rotations
¶ Symmetry rotation matrices. The invertions are not included for centrosymmetrical crystals.
-
scaled_primitive_cell
¶ Primitive cell in scaled coordinates as a matrix with the primitive vectors along the rows.
-
setting
¶ Space group setting. Either one or two.
-
subtrans
¶ Translations vectors belonging to cell-sub-translations.
-
symbol
¶ Hermann-Mauguin (or international) symbol for the space group.
-
symmetry_normalised_reflections
(hkl)[source]¶ Returns an array of same size as hkl, containing the corresponding symmetry-equivalent reflections of lowest indices.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.symmetry_normalised_reflections([[2, 0, 0], [0, 2, 0]]) array([[ 0, 0, -2], [ 0, 0, -2]])
-
symmetry_normalised_sites
(scaled_positions)[source]¶ Returns an array of same size as scaled_positions, containing the corresponding symmetry-equivalent sites within the unit cell of lowest indices.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.symmetry_normalised_sites([[0.0, 0.5, 0.5], [1.0, 1.0, 0.0]]) array([[ 0., 0., 0.], [ 0., 0., 0.]])
-
tag_sites
(scaled_positions, symprec=0.001)[source]¶ Returns an integer array of the same length as scaled_positions, tagging all equivalent atoms with the same index.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.tag_sites([[0.0, 0.0, 0.0], ... [0.5, 0.5, 0.0], ... [1.0, 0.0, 0.0], ... [0.5, 0.0, 0.0]]) array([0, 0, 0, 1])
-
translations
¶ Symmetry translations. The invertions are not included for centrosymmetrical crystals.
-
unique_reflections
(hkl)[source]¶ Returns a subset hkl containing only the symmetry-unique reflections.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.unique_reflections([[ 2, 0, 0], ... [ 0, -2, 0], ... [ 2, 2, 0], ... [ 0, -2, -2]]) array([[2, 0, 0], [2, 2, 0]])
-
unique_sites
(scaled_positions, symprec=0.001, output_mask=False)[source]¶ Returns a subset of scaled_positions containing only the symmetry-unique positions. If output_mask is True, a boolean array masking the subset is also returned.
Example:
>>> from ase.lattice.spacegroup import Spacegroup >>> sg = Spacegroup(225) # fcc >>> sg.unique_sites([[0.0, 0.0, 0.0], ... [0.5, 0.5, 0.0], ... [1.0, 0.0, 0.0], ... [0.5, 0.0, 0.0]]) array([[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ]])
Created on Sun May 1 22:49:20 2016
@author: cjs14
-
class
ipymd.data_input.base.
DataInput
[source]¶ Bases:
object
Data is divided into two levels; atomic and meta
- atom is a series of tables, one for each timestep, containing variables (columns) for each atom (rows)
- meta is a table containing variables (columns) for each configuration (rows)
Created on Wed May 18 22:24:10 2016
@author: cjs14
adapted from from http://physics.bu.edu/~erikl/research/tools/crystals/read_cif.py
-
class
ipymd.data_input.cif.
CIF
[source]¶ Bases:
ipymd.data_input.base.DataInput
Data is divided into two levels; atomic and meta
- atom is a series of tables, one for each timestep, containing variables (columns) for each atom (rows)
- meta is a table containing variables (columns) for each configuration (rows)
-
setup_data
(file_path, override_abc=[], ignore_overlaps=False)[source]¶ Build a crystal from a Crystallographic Information File (.cif)
Parameters: file_path (str) – path to file override_abc : [] or [a,b,c]
if not empty, will override a, b, c length parameters given in fileNotes
here is a typical example of a CIF file:
_cell_length_a 4.916 _cell_length_b 4.916 _cell_length_c 5.4054 _cell_angle_alpha 90 _cell_angle_beta 90 _cell_angle_gamma 120 _cell_volume 113.131 _exptl_crystal_density_diffrn 2.646 _symmetry_space_group_name_H-M ‘P 32 2 1’ loop_ _space_group_symop_operation_xyz
‘x,y,z’ ‘y,x,2/3-z’ ‘-y,x-y,2/3+z’ ‘-x,-x+y,1/3-z’ ‘-x+y,-x,1/3+z’ ‘x-y,-y,-z’loop_ _atom_site_label _atom_site_fract_x _atom_site_fract_y _atom_site_fract_z Si 0.46970 0.00000 0.00000 O 0.41350 0.26690 0.11910
Created on Mon May 16 01:23:11 2016
@author: cjs14
Adapted from chemlab which, in turn, was adapted from ASE https://wiki.fysik.dtu.dk/ase/ Copyright (C) 2010, Jesper Friis
-
class
ipymd.data_input.crystal.
Crystal
[source]¶ Bases:
ipymd.data_input.base.DataInput
Data is divided into two levels; atomic and meta
- atom is a series of tables, one for each timestep, containing variables (columns) for each atom (rows)
- meta is a table containing variables (columns) for each configuration (rows)
-
setup_data
(positions, atom_type, group, cellpar=[1.0, 1.0, 1.0, 90, 90, 90], repetitions=[1, 1, 1], mass_map={}, charge_map={})[source]¶ Build a crystal from atomic positions, space group and cell parameters (in Angstroms)
Parameters: - positions (list of coordinates) – A list of the fractional atomic positions
- atom_type (list of atom type) – The atom types corresponding to the positions, the atoms will be translated in all the equivalent positions.
- group (int | str) – Space group given as its number in International Tables NB: to see mappings from Hermann–Mauguin notation, etc, use the get_spacegroup_df function in this module
- repetitions – Repetition of the unit cell in each direction
- cellpar – Unit cell parameters (in Angstroms and degrees)
- mass_map (dict of atom masses) – mapping of atom masses to atom types
- charge_map (dict of atom charges) – mapping of atom charges to atom types
- function was taken and adapted from the spacegroup module (This) –
:param found in ASE.: :param The module spacegroup module was originally developed by Jesper: :param Frills.:
Example
from ipymd.data_input import crystal c = crystal.Crystal([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]],
[‘Na’, ‘Cl’], 225, cellpar = [5.4, 5.4, 5.4, 90, 90, 90], repetitions = [5, 5, 5])c.get_atom_data() c.get_simulation_box()
Created on Mon May 16 01:15:56 2016
@author: cjs14
-
class
ipymd.data_input.lammps.
LAMMPS_Input
[source]¶ Bases:
ipymd.data_input.base.DataInput
Data is divided into two levels; atomic and meta
- atom is a series of tables, one for each timestep, containing variables (columns) for each atom (rows)
- meta is a table containing variables (columns) for each configuration (rows)
-
class
ipymd.data_input.lammps.
LAMMPS_Output
[source]¶ Bases:
ipymd.data_input.base.DataInput
Data is divided into two levels; atomic and meta
- atom is a series of tables, one for each timestep, containing variables (columns) for each atom (rows)
- meta is a table containing variables (columns) for each configuration (rows)
-
setup_data
(atom_path='', sys_path='', sys_sep=' ', atom_map={}, incl_atom_step=False, incl_sys_data=True)[source]¶ Data divided into two levels; meta and atom
- atom_map : dict
- mapping of atom level variable names e.g. {‘C_var[1]’:’x’}
- sys_sep : str
- the separator between variables in the system data file
- incl_atom_time : bool
- include time according to atom file in column ‘atom_step’ of meta
- incl_sys_data : bool
- include system data in the single step meta data
Notes
Meta level data created with fix print, e.g.;
fix sys_info all print 100 “${t} ${natoms} ${temp}” & title “time natoms temp” file system.dump screen noAtom level data created with dump, e.g.;
dump atom_info all custom 100 atom.dump id type x y z mass q OR (file per configuration) dump atom_info all custom 100 atom_*.dump id type xs ys zs mass q
-
ipymd.data_input.lammps.
natural_keys
(text)[source]¶ alist.sort(key=natural_keys) sorts in human order, e.g. [‘1’,‘2’,‘100’] instead of [‘1’,‘100’,‘2’] http://nedbatchelder.com/blog/200712/human_sorting.html
ipymd.plotting package¶
Created on Fri Jul 1 16:45:06 2016
@author: cjs14
-
class
ipymd.plotting.plotter.
Plotter
(nrows=1, ncols=1, figsize=(5, 4))[source]¶ Bases:
object
a class to deal with data plotting
-
figure
¶ matplotlib.figure
the figure
-
axes
¶ list or single matplotlib.axes
if more than one then returns a list (ordered in reading direction), else returns one instance
-
add_image
(image, axes=0, interpolation='bicubic', hide_axes=True, width=1.0, height=1.0, origin=(0.0, 0.0), **kwargs)[source]¶ add image to axes
-
add_image_annotation
(img, xy=(0, 0), arrow_xy=None, axes=0, zoom=1, xytype='axes points', arrow_xytype='data', arrowprops={'connectionstyle': 'arc3, rad=0.2', 'alpha': 0.4, 'arrowstyle': 'simple', 'facecolor': 'black'})[source]¶ add an image to the plot
coordtype:
argument coordinate system ‘figure points’ points from the lower left corner of the figure ‘figure pixels’ pixels from the lower left corner of the figure ‘figure fraction’ 0,0 is lower left of figure and 1,1 is upper right ‘axes points’ points from lower left corner of axes ‘axes pixels’ pixels from lower left corner of axes ‘axes fraction’ 0,0 is lower left of axes and 1,1 is upper right ‘data’ use the axes data coordinate system for arrowprops see http://matplotlib.org/users/annotations_guide.html#annotating-with-arrow
-
axes
-
display_plot
(tight_layout=False)[source]¶ display plot in IPython
if tight_layout is True it may crop anything outside axes
-
figure
-
-
ipymd.plotting.plotter.
animation_contourf
(x_iter, y_iter, z_iter, interval=20, xlim=(0, 1), ylim=(0, 1), zlim=(0, 1.0), cmap='viridis', cbar=True, incl_controls=True, plot=None, ax=0, **plot_kwargs)[source]¶ create an animation of multiple x,y data sets
- x_iter : iterable
- any iterable of x data sets, e.g. [[1,2,3],[4,5,6]]
- y_iter : iterable
- an iterable of y data sets, e.g. [[1,2,3],[4,5,6]]
- y_iter : iterable
- an iterable of z(x,y) data sets, each set must be of shape (len(x), len(y))
- interval : int
- draws a new frame every interval milliseconds
- xlim : tuple
- the x_limits for the axes (ignored if using existing plotter)
- ylim : tuple
- the y_limits for the axes (ignored if using existing plotter)
- zlim : tuple
- the z_limits for the colormap
- cmap : str or matplotlib.cm
- the colormap to use (see http://matplotlib.org/examples/color/colormaps_reference.html)
- incl_controls : bool
- include Javascript play controls
- plot : ipymd.plotting.Plotter
- an existing plotter object
- ax : int
- the id number of the axes on which to plot (if using existing plotter)
- plot_kwargs : various
- key word arguments to pass to plot method, e.g. marker=’o’, color=’b’, ...
Returns: html – a html object Return type: IPython.core.display.HTML Notes
x_iter and y_iter can be yield functions such as:
def y_iter(x_iter): for xs in x_iter: yield [i**2 for i in xs]
This means that the values do not have to be necessarily pre-computed.
-
ipymd.plotting.plotter.
animation_line
(x_iter, y_iter, interval=20, xlim=(0, 1), ylim=(0, 1), incl_controls=True, plot=None, ax=0, **plot_kwargs)[source]¶ create an animation of multiple x,y data sets
- x_iter : iterable
- any iterable of x data sets, e.g. [[1,2,3],[4,5,6]]
- y_iter : iterable
- an iterable of y data sets, e.g. [[1,2,3],[4,5,6]]
- interval : int
- draws a new frame every interval milliseconds
- xlim : tuple
- the x_limits for the axes (ignored if using existing plotter)
- ylim : tuple
- the y_limits for the axes (ignored if using existing plotter)
- incl_controls : bool
- include Javascript play controls
- plot : ipymd.plotting.Plotter
- an existing plotter object
- ax : int
- the id number of the axes on which to plot (if using existing plotter)
- plot_kwargs : various
- key word arguments to pass to plot method, e.g. marker=’o’, color=’b’, ...
Returns: html – a html object Return type: IPython.core.display.HTML Notes
x_iter and y_iter can be yield functions such as:
def y_iter(x_iter): for xs in x_iter: yield [i**2 for i in xs]
This means that the values do not have to be necessarily pre-computed.
-
ipymd.plotting.plotter.
animation_scatter
(x_iter, y_iter, interval=20, xlim=(0, 1), ylim=(0, 1), incl_controls=True, plot=None, ax=0, **plot_kwargs)[source]¶ create an animation of multiple x,y data sets
- x_iter : iterable
- any iterable of x data sets, e.g. [[1,2,3],[4,5,6]]
- y_iter : iterable
- an iterable of y data sets, e.g. [[1,2,3],[4,5,6]]
- interval : int
- draws a new frame every interval milliseconds
- xlim : tuple
- the x_limits for the axes (ignored if using existing plotter)
- ylim : tuple
- the y_limits for the axes (ignored if using existing plotter)
- incl_controls : bool
- include Javascript play controls
- plot : ipymd.plotting.Plotter
- an existing plotter object
- ax : int
- the id number of the axes on which to plot (if using existing plotter)
- plot_kwargs : various
- key word arguments to pass to plot method, e.g. marker=’o’, color=’b’, ...
Returns: html – a html object Return type: IPython.core.display.HTML Notes
x_iter and y_iter can be yield functions such as:
def y_iter(x_iter): for xs in x_iter: yield [i**2 for i in xs]
This means that the values do not have to be necessarily pre-computed.
-
ipymd.plotting.plotter.
style
(style)[source]¶ A context manager to apply matplotlib style settings from a style specification.
Popular styles include; default, ggplot, xkcd, and are used in the the following manner:
with ipymd.plotting.style('default'): plot = ipymd.plotting.Plotter() plot.display_plot()
Parameters: style (str, dict, or list) – A style specification. Valid options are:
str The name of a style or a path/URL to a style file. For a list of available style names, see style.available. dict Dictionary with valid key/value pairs for matplotlib.rcParams. list A list of style specifiers (str or dict) applied from first to last in the list.
ipymd.visualise package¶
-
class
ipymd.visualise.opengl.postprocessing.base.
AbstractEffect
(*args, **kwargs)[source]¶ Bases:
object
Interface for a generic post processing effect.
A subclass of AbstractEffect can be used by a
QChemlabWidget
to provide post-processing effects such as outlines, gamma correction, approximate anti-aliasing, or screen space ambient occlusion.-
on_resize
(w, h)[source]¶ Optionally, subclasses can override on_resize. This method is useful if the post-processing effect requires additional creation of textures that need to hold multiple passes.
-
render
(fb, textures)[source]¶ Subclasses should override this method to draw the post-processing effect by using the framebuffer fb (represented as an integer generated by glGenFramebuffers).
The textures corresponding to the model rendering and the previous post-processing effects are passed through the dictionary textures.
The textures passed by default are “color”, “depth” and “normal” and are instances of
chemlab.graphics.Texture
.
-
-
class
ipymd.visualise.opengl.postprocessing.noeffect.
NoEffect
(widget)[source]¶ Bases:
ipymd.visualise.opengl.postprocessing.base.AbstractEffect
Re-render the object without implementing any effect.
This renderer serves as an example, and can be used to access the textures used for the rendering through the texture attribute.
This texture can be used to dump the image being rendered.
Created on Sun May 15 20:10:20 2016
@author: cjs14
added patch to allow for transparent atoms when using ‘impostors’ backend & changed to have pre-processing of colors and radii
-
class
ipymd.visualise.opengl.renderers.atom.
AtomRenderer
(widget, r_array, radii, colorlist, backend='impostors', shading='phong', transparent=True)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.AbstractRenderer
Render atoms by using different rendering methods.
Parameters
- widget:
- The parent QChemlabWidget
- r_array: np.ndarray((NATOMS, 3), dtype=float)
- The atomic coordinate array
- backend: “impostors” | “polygons” | “points”
- You can choose the rendering method between the sphere impostors, polygonal sphere and points.
-
class
ipymd.visualise.opengl.renderers.base.
AbstractRenderer
(widget, *args, **kwargs)[source]¶ Bases:
object
AbstractRenderer is the standard interface for renderers. Each renderer have to implement an initialization function __init__ and a draw method to do the actual drawing using OpenGL or by using other, more basic, renderers.
Usually the renderers have also some custom functions that they use to update themselves. For example a SphereRenderer implements the function update_positions to move the spheres around without having to regenerate all of the other properties.
See also
/graphics
for a tutorial on how to develop a simple renderer.Parameters
- widget:
chemlab.graphics.QChemlabWidget
- The parent QChemlabWidget. Renderers can use the widget to access the camera, lights, and other informations.
args, kwargs: Any other argument that they may use.
- widget:
-
class
ipymd.visualise.opengl.renderers.base.
DefaultRenderer
(widget)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
Same as
ShaderBaseRenderer
with the default shaders.You can find the shaders in
chemlab/graphics/renderers/shaders/
under the names ofdefault_persp.vert
anddefault_persp.frag
.
-
class
ipymd.visualise.opengl.renderers.base.
ShaderBaseRenderer
(widget, vertex, fragment)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.AbstractRenderer
Instruments OpenGL with a vertex and a fragment shader.
This renderer automatically binds light and camera information. Subclasses should not reimplement the
draw
method but thedraw_vertices
method where you can bind and draw the objects.Parameters
- widget:
- The parent
QChemlabWidget
- vertex: str
- Vertex program as a string
- fragment: str
- Fragment program as a string
Created on Mon May 16 10:53:56 2016
@author: cjs14
added patch to allow for line width selection
-
class
ipymd.visualise.opengl.renderers.box.
BoxRenderer
(widget, vectors, origin=<Mock object>, color=(0, 0, 0, 255), width=1.5)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
Used to render one wireframed box.
Parameters
- widget:
- The parent QChemlabWidget
- vectors: np.ndarray((3,3), dtype=float)
- The three vectors representing the sides of the box.
- origin: np.ndarray((3,3), dtype=float), default to zero
- The origin of the box.
- color: 4 int tuple
- r,g,b,a color in the range [0,255]
- width: float
- width of wireframe lines
Created on Mon May 16 12:41:12 2016
@author: cjs14
-
class
ipymd.visualise.opengl.renderers.hexagon.
HexagonRenderer
(widget, vectors, origin=<Mock object>, color=(0, 0, 0, 255), width=1.5)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
Used to render one wireframed hexagonal prism.
Parameters
- widget:
- The parent QChemlabWidget
- vectors: np.ndarray((2,3), dtype=float)
- The two vectors representing the orthogonal a,c crystal vectors.
- origin: np.ndarray((3,), dtype=float), default to zero
- The origin of the box.
- color: 4 int tuple
- r,g,b,a color in the range [0,255]
- width: float
- width of wireframe lines
-
class
ipymd.visualise.opengl.renderers.line.
LineRenderer
(widget, startends, colors, width=1.5)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
Render a set of lines.
Parameters
- widget:
- The parent QChemlabWidget
- startends: np.ndarray((NLINES, 2, 3), dtype=float)
Start and end position of each line in the form of an array:
s1 = [0.0, 0.0, 0.0] startends = [[s1, e1], [s2, e2], ..]
- colors: np.ndarray((NLINES, 2, 4), dtype=np.uint8)
- The corresponding color of each extrema of each line.
-
class
ipymd.visualise.opengl.renderers.point.
PointRenderer
(widget, positions, colors)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
Render colored points.
Parameters
- widget:
- The parent QChemlabWidget
- positons: np.ndarray((NPOINTS, 3), dtype=np.float32)
- Positions of the points to draw.
- colors: np.ndarray((NPOINTS, 4), dtype=np.uint8) or list of tuples
- Color of each point in the (r,g,b,a) format in the interval [0, 255]
-
class
ipymd.visualise.opengl.renderers.sphere.
Sphere
(radius, center, parallels=20, meridians=15, color=[0.0, 0.0, 0.0, 0.0])[source]¶ Bases:
object
Create a Sphere object specifying its radius its center point. You can modulate its smoothness using the parallel and meridians settings.
-
class
ipymd.visualise.opengl.renderers.sphere.
SphereRenderer
(widget, poslist, radiuslist, colorlist, shading='phong')[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.AbstractRenderer
Renders a set of spheres.
The method used by this renderer is approximating a sphere by using triangles. While this is reasonably fast, for best performance and animation you should use
SphereImpostorRenderer
Parameters
- widget:
- The parent
QChemlabWidget
- poslist: np.ndarray((NSPHERES, 3), dytpe=float)
- A position array. While there aren’t dimensions, in the context of chemlab 1 unit of space equals 1 nm.
- radiuslist: np.ndarray(NSPHERES, dtype=float)
- An array with the radius of each sphere.
- colorlist: np.ndarray(NSPHERES, 4) or list of tuples
- An array with the color of each sphere. Suitable colors are
those found in
chemlab.graphics.colors
or any tuple with values (r, g, b, a) in the range [0, 255]
-
class
ipymd.visualise.opengl.renderers.sphere_imp.
SphereImpostorRenderer
(viewer, poslist, radiuslist, colorlist, transparent=False, shading='phong')[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.ShaderBaseRenderer
The interface is identical to
SphereRenderer
but uses a different drawing method.The spheres are squares that always face the user. Each point of the sphere, along with the lighting, is calculated in the fragment shader, resulting in a perfect sphere.
SphereImpostorRenderer is an extremely fast rendering method, it is perfect for rendering a lot of spheres ( > 50000) and for animations.
Created on Mon May 16 09:55:43 2016
@author: cjs14
added patch to allow for transparent surface
-
class
ipymd.visualise.opengl.renderers.triangle.
TriangleRenderer
(widget, vertices, normals, colors, shading='phong', transparent=False, wireframe=False)[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.DefaultRenderer
Renders an array of triangles.
A lot of renderers are built on this, for example
SphereRenderer
. The implementation is relatively fast since it’s based on VertexBuffers.Parameters
- widget:
- The parent QChemlabWidget
- vertices: np.ndarray((NTRIANGLES*3, 3), dtype=float)
- The triangle vertices, keeping in mind the unwinding order. If the face of the triangle is pointing outwards, the vertices should be provided in clokckwise order.
- normals: np.ndarray((NTRIANGLES*3, 3), dtype=float)
- The normals to each of the triangle vertices, used for lighting calculations.
- colors: np.ndarray((NTRIANGLES*3, 4), dtype=np.uint8)
- Color for each of the vertices in (r,g,b,a) values in the interval [0, 255]
TriangleRenderer is the basics for other shapes, we pass just triangle vertices and we got the result.
-
class
ipymd.visualise.opengl.renderers.triangles.
TriangleRenderer
(widget, vertices, normals, colors, shading='phong')[source]¶ Bases:
ipymd.visualise.opengl.renderers.base.DefaultRenderer
Renders an array of triangles.
A lot of renderers are built on this, for example
SphereRenderer
. The implementation is relatively fast since it’s based on VertexBuffers.Parameters
- widget:
- The parent QChemlabWidget
- vertices: np.ndarray((NTRIANGLES*3, 3), dtype=float)
- The triangle vertices, keeping in mind the unwinding order. If the face of the triangle is pointing outwards, the vertices should be provided in clokckwise order.
- normals: np.ndarray((NTRIANGLES*3, 3), dtype=float)
- The normals to each of the triangle vertices, used for lighting calculations.
- colors: np.ndarray((NTRIANGLES*3, 4), dtype=np.uint8)
- Color for each of the vertices in (r,g,b,a) values in the interval [0, 255]
Module to provide a nice camera for 3d applications
-
class
ipymd.visualise.opengl.camera.
Camera
[source]¶ Our viewpoint on the 3D world. The Camera class can be used to access and modify from which point we’re seeing the scene.
It also handle the projection matrix (the matrix we apply to project 3d points onto our 2d screen).
-
position
¶ Type: np.ndarray(3, float) Default: np.array([0.0, 0.0, 5.0]) The position of the camera. You can modify this attribute to move the camera in various directions using the absoule x, y and z coordinates.
-
a, b, c
Type: np.ndarray(3), np.ndarray(3), np.ndarray(3) dtype=float Default: a: np.ndarray([1.0, 0.0, 0.0]) b: np.ndarray([0.0, 1.0, 0.0]) c: np.ndarray([0.0, 0.0, -1.0]) Those three vectors represent the camera orientation. The
a
vector points to our right, theb
points upwards andc
in front of us.By default the camera points in the negative z-axis direction.
-
pivot
¶ Type: np.ndarray(3, dtype=float) Default: np.array([0.0, 0.0, 0.0]) The point we will orbit around by using
Camera.orbit_x()
andCamera.orbit_y()
.
-
matrix
¶ Type: np.ndarray((4,4), dtype=float) Camera matrix, it contains the rotations and translations needed to transform the world according to the camera position. It is generated from the
a
,``b``,``c`` vectors.
-
projection
¶ Type: np.ndarray((4, 4),dtype=float) Projection matrix, generated from the projection parameters.
-
z_near, z_far
Type: float, float Near and far clipping planes. For more info refer to: http://www.lighthouse3d.com/tutorials/view-frustum-culling/
-
fov
¶ Type: float field of view in degrees used to generate the projection matrix.
-
aspectratio
¶ Type: float Aspect ratio for the projection matrix, this should be adapted when the application window is resized.
-
autozoom
(points)[source]¶ Fit the current view to the correct zoom level to display all points.
The camera viewing direction and rotation pivot match the geometric center of the points and the distance from that point is calculated in order for all points to be in the field of view. This is currently used to provide optimal visualization for molecules and systems
Parameters
- points: np.ndarray((N, 3))
- Array of points.
-
matrix
-
mouse_rotate
(dx, dy)[source]¶ Convenience function to implement the mouse rotation by giving two displacements in the x and y directions.
-
mouse_zoom
(inc)[source]¶ Convenience function to implement a zoom function.
This is achieved by moving
Camera.position
in the direction of theCamera.c
vector.
-
orbit_x
(angle)[source]¶ Same as
orbit_y()
but the axis of rotation is theCamera.b
vector.We rotate around the point like if we sit on the side of a salad spinner.
-
orbit_y
(angle)[source]¶ Orbit around the point
Camera.pivot
by the angle angle expressed in radians. The axis of rotation is the camera “right” vector,Camera.a
.In practice, we move around a point like if we were on a Ferris wheel.
-
projection
-
restore
(state)[source]¶ Restore the camera state, passed as a state dictionary. You can obtain a previous state from the method Camera.state.
-
state
()[source]¶ Return the current camera state as a dictionary, it can be restored with Camera.restore.
-
unproject
(x, y, z=-1.0)[source]¶ Receive x and y as screen coordinates and returns a point in world coordinates.
This function comes in handy each time we have to convert a 2d mouse click to a 3d point in our space.
Parameters
- x: float in the interval [-1.0, 1.0]
- Horizontal coordinate, -1.0 is leftmost, 1.0 is rightmost.
- y: float in the interval [1.0, -1.0]
- Vertical coordinate, -1.0 is down, 1.0 is up.
- z: float in the interval [1.0, -1.0]
- Depth, -1.0 is the near plane, that is exactly behind our screen, 1.0 is the far clipping plane.
Return type: np.ndarray(3,dtype=float) Returns: The point in 3d coordinates (world coordinates).
-
-
ipymd.visualise.opengl.shaders.
compileShader
(source, shaderType)[source]¶ Compile shader source of given type
source – GLSL source-code for the shader shaderType – GLenum GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, etc,
returns GLuint compiled shader reference raises RuntimeError when a compilation failure occurs
Texture data structures
Created on Sun May 1 23:47:03 2016
@author: cjs14
-
class
ipymd.visualise.visualise_sim.
Visualise_Sim
(units='real')[source]¶ Bases:
object
For units real, these are the units:
mass = grams/mole distance = Angstroms time = femtoseconds energy = Kcal/mole velocity = Angstroms/femtosecond force = Kcal/mole-Angstrom torque = Kcal/mole temperature = Kelvin pressure = atmospheres dynamic viscosity = Poise charge = multiple of electron charge (1.0 is a proton) dipole = charge*Angstroms electric field = volts/Angstrom density = gram/cm^dim-
add_atoms
(atoms_df, spheres=True, illustrate=False)[source]¶ add atoms to visualisation
- atoms_df : pandas.DataFrame
- a table of atom data, must contain columns; x, y, z, radius, color and transparency
- spheres : bool
- whether the atoms are rendered as spheres or points
- illustrate : str
- if True, atom shading is more indicative of an illustration
-
add_axes
(axes=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], length=1.0, offset=(-1.2, 0.2), colors=('red', 'green', 'blue'), width=1.5)[source]¶ add axes
- axes : np.array(3,3)
- to turn off axes, set to None
- axes_offset : tuple
- x, y offset from top top-left atom
-
add_bonds
(atoms_df, bonds_df, cylinders=False, illustrate=False, linewidth=5)[source]¶ add bonds to visualisation
- atoms_df : pandas.DataFrame
- a table of atom data, must contain columns; x, y, z
- bonds_df : list
- a table of bond data, must contain; start, end, radius, color, transparency to/from refer to the atoms_df iloc (not necessarily the index number!)
- cylinders : bool
- whether the bonds are rendered as cylinders or lines
- illustrate : str
- if True, atom shading is more indicative of an illustration
-
add_box
(a, b, c, origin=[0, 0, 0], color='black', width=1)[source]¶ add wireframed box to visualisation
- a : np.ndarray(3, dtype=float)
- The a vectors representing the sides of the box.
- b : np.ndarray(3, dtype=float)
- The b vectors representing the sides of the box.
- c : np.ndarray(3, dtype=float)
- The c vectors representing the sides of the box.
- origin : np.ndarray((3,3), dtype=float), default to zero
- The origin of the box.
- color : str
- the color of the wireframe, in chemlab colors
-
add_box_from_meta
(meta, color='black', width=1)[source]¶ a shortcut for adding boxes using a panda.Series containing a,b,c,origin
-
add_hexagon
(vectors, origin=<Mock object>, color='black', width=1)[source]¶ add wireframed hexagonal prism to visualisation
- vectors : np.ndarray((2,3), dtype=float)
- The two vectors representing the orthogonal a,c directions.
- origin : np.ndarray((3,3), dtype=float), default to zero
- The origin of the hexagon (representing center of hexagon)
- color : str
- the color of the wireframe, in chemlab colors
-
add_plane
(vectors, origin=<Mock object>, rev_normal=False, color='red', alpha=1.0)[source]¶ add square plane to visualisation
- vectors : np.ndarray((2,3), dtype=float)
- The two vectors representing the edges of the plane.
- origin : np.ndarray((3,3), dtype=float), default to zero
- The origin of the plane.
- rev_normal : bool
- whether to reverse direction of normal (for lighting calculations)
- color : str
- the color of the plane, in chemlab colors
-
basic_vis
(atoms_df=None, meta=None, spheres=True, illustrate=False, xrot=0, yrot=0, zrot=0, fov=10.0, axes=<Mock object>, axes_length=1.0, axes_offset=(-1.2, 0.2), size=400, quality=5)[source]¶ basic visualisation shortcut
invoking add_atoms, add_box (if meta), add_axes, get_image and visualise functions
-
create_textline_image
(text, fontsize=10, color=(0, 0, 0), background=(255, 255, 255), boxsize=(1000, 20))[source]¶ create a PIL image from a line of text
-
get_image
(xrot=0, yrot=0, zrot=0, fov=5.0, size=400, quality=5, zoom_extents=None, trim_whitespace=True)[source]¶ get image of visualisation
NB: x-axis horizontal, y-axis vertical, z-axis out of page
Parameters: - rotx (float) – rotation about x (degrees)
- roty (float) – rotation about y (degrees)
- rotz (float) – rotation about z (degrees)
- fov (float) – field of view angle (degrees)
- size (float) – size of image
- quality (float) – quality of image (pixels per point), note: higher quality will take longer to render
- zoom_extents (None or np.ndarray((N, 3))) – define an array of points to autozoom image, if None then computed automatically
- trim_whitespace (bool) – whether to trim whitspace around image
Returns: image
Return type: PIL.Image
-
open_qtview
(xrot=0, yrot=0, zrot=0, fov=5.0, thickness=1, zoom_extents=None)[source]¶ open a qt viewer of the objects
Parameters: - rotx (float) – rotation about x (degrees)
- roty (float) – rotation about y (degrees)
- rotz (float) – rotation about z (degrees)
- fov (float) – field of view angle (degrees)
- thickness (float) – multiplier for thickness of lines for some objects
- zoom_extents (None or np.ndarray((N, 3))) – define an array of points to autozoom image, if None then computed automatically
Returns: viewer – the qt viewing window
Return type: PyQt4.QtGui.QMainWindow
-
Submodules¶
ipymd.atom_manipulation module¶
Created on Mon May 16 08:15:13 2016
@author: cjs14
-
class
ipymd.atom_manipulation.
Atom_Manipulation
(atom_df, meta_series=None, undos=1)[source]¶ Bases:
object
a class to manipulate atom data
- atom_df : pandas.DataFrame
- containing columns; x, y, z, type
- meta_series : pandas.Series
- containing columns; origin, a, b, c to define unit cell if none it will be constructed from the min/max x, y, z values
- undos : int
- number of past dataframes to save
-
apply_map
(vmap, column, default=False, type_col='type')[source]¶ change values in a column, according to a mapping of another column
- vmap : dict or str
- A dictionary mapping values, or a string associated with a column in the ipymd.shared.atom_data() dataframe (e.g. color and RVdW)
- column : str
- the column to change
- default : various
- the default value to put when the type key cannot be found, if False then the original value will not be overwritten
-
change_type_variable
(atom_type, variable, value, type_col='type')[source]¶ change particular variable for one atom type
-
change_variables
(map_dict, vtype='type')[source]¶ change particular variables according to the map_dict
-
color_by_categories
(colname, cmap='jet', sort=True)[source]¶ change colors to map
- colname : string
- a column of the dataframe that contains categories by which to color
- cmap : string
- the colormap to apply, see available at http://matplotlib.org/examples/color/colormaps_reference.html
-
color_by_index
(cmap='jet', minv=None, maxv=None)[source]¶ change colors to map index values
- cmap : string
- the colormap to apply, see available at http://matplotlib.org/examples/color/colormaps_reference.html
- minv, maxv : float
- optional min, max cmap value, otherwise take min, max value found in column
-
color_by_variable
(colname, cmap='jet', minv=None, maxv=None)[source]¶ change colors to map
- colname : string
- a coloumn of the dataframe that contains numbers by which to color
- cmap : string
- the colormap to apply, see available at http://matplotlib.org/examples/color/colormaps_reference.html
- minv, maxv : float
- optional min, max cmap value, otherwise take min, max value found in column
-
df
¶
-
filter_inside_box
(vectors, origin=<Mock object>)[source]¶ return only atoms inside box
- vectors : np.array((3,3))
- a, b, c vectors
origin : np.array((1,3))
-
filter_inside_hexagon
(vectors, origin=<Mock object>)[source]¶ return only atoms inside hexagonal prism
- vectors : np.array((2,3))
- a, c vectors
origin : np.array((1,3))
-
filter_inside_pts
(points)[source]¶ return only atoms inside the bounding shape of a set of points
points : np.array((N,3))
-
group_atoms_as_mols
(atom_ids, name, remove_atoms=True, mean_xyz=True, color='red', transparency=1.0, radius=1.0)[source]¶ combine atoms into a molecule atom_ids : list of lists
list of dataframe indexes for each molecule- name : string
- name of molecule
- remove_atoms : bool
- remove the grouped atoms from the dataframe
- mean_xyz : bool
- use the mean coordinate of atoms for molecule, otherwise use coordinate of first atom
-
meta
¶
-
repeat_cell
(a=1, b=1, c=1, original_first=False)[source]¶ repeat atoms along a, b, c directions (and update unit cell)
- a : int or tuple
- repeats in ‘a’ direction, if tuple then defines repeats in -/+ direction
- b : int or tuple
- repeats in ‘b’ direction, if tuple then defines repeats in -/+ direction
- c : int or tuple
- repeats in ‘c’ direction, if tuple then defines repeats in -/+ direction
- original_first: bool
- if True, the original atoms will be first in the DataFrame
-
rotate
(angle, vector=[1, 0, 0], update_uc=True)[source]¶ rotate the clockwise about the given axis vector by theta degrees.
e.g. for rotate_atoms(90,[0,0,1]); [0,1,0] -> [1,0,0]
- angle : float
- rotation angle in degrees
- vector : iterable
- vector to rotate around [x0,y0,z0]
- update_uc : bool
- update unit cell (a,b,c,origin) to match rotation
-
slice_absolute
(amin=0, amax=None, bmin=0, bmax=None, cmin=0, cmax=None, incl_max=False, update_uc=True, delta=0.01)[source]¶ slice along a,b,c directions (from origin) given absolute vector length
if amax, bmax or cmax is None, then will use the vector length
- update_uc : bool
- update unit cell (a,b,c,origin) to match slice
- incl_max : bool
- whether to slice < (False) <= (True) max values
- delta : float
- retain atoms within ‘delta’ fraction outside of slice plane)
-
slice_fraction
(amin=0, amax=1, bmin=0, bmax=1, cmin=0, cmax=1, incl_max=False, update_uc=True, delta=0.01)[source]¶ slice along a,b,c directions (from origin) as fraction of vector length
- incl_max : bool
- whether to slice < (False) <= (True) max values
- update_uc : bool
- update unit cell (a,b,c,origin) to match slice
- delta : float
- retain atoms within ‘delta’ fraction outside of slice plane)
ipymd.data_output module¶
Created on Mon May 23 17:55:14 2016
@author: cjs14
-
class
ipymd.data_output.
Data_Output
(atom_df, abc, origin=<Mock object>)[source]¶ Bases:
object
-
save_lammps
(outpath='out.lammps', overwrite=False, atom_type='atomic', header='', mass_map={})[source]¶ to adhere to http://lammps.sandia.gov/doc/read_data.html?highlight=read_data
Parameters: Example
In [1]: import pandas as pd In [2]: df = pd.DataFrame([[‘Fe’,2,3,4,1],
[‘Cr’,2,3,3,-1], [‘Fe’,4,3,1,1]],columns=[‘type’,’xs’,’ys’,’zs’,’q’])In [3]: from ipymd.data_output import Data_Output as data_out In [4]: data = data_out(df, [[1,0,0],[0,1,0],[0,0,1]]) In [5]: data.save_lammps(‘test.lammps’, atom_type=’charge’, overwrite=True,
header=’my header’)In [6]: cat test.lammps # This file was created by ipymd (v0.0.1) on 2016-05-23 20:51:16 # type map: {‘Cr’: 2, ‘Fe’: 1} # my header
3 atoms 2 atom types
# simulation box boundaries 0.0000 1.0000 xlo xhi 0.0000 1.0000 ylo yhi 0.0000 1.0000 zlo zhi 0.0000 0.0000 0.0000 xy xz yz
Atoms
1 1 1.0000 2.0000 3.0000 4.0000 2 2 -1.0000 2.0000 3.0000 3.0000 3 1 1.0000 4.0000 3.0000 1.0000
-