{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Plotting Density of States with
Plotly and Pymatgen"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### About the Author:\n",
"\n",
"This notebook was contributed by plotly user [Germain Salvato-Vallverdu](https://plotly.com/~gvallverdu). You can follow him on [GitHub](https://github.com/gVallverdu?tab=activity) or visit [his webpage](http://gvallver.perso.univ-pau.fr/)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Introduction"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook will go over an example for plotting the density of states and the band diagram of Silicon using python with [pymatgen](http://pymatgen.org/) and [plotly](https://plotly.com/) packages.\n",
"\n",
"* [pymatgen](http://pymatgen.org/) : (Python Materials Genomics) A robust, open-source Python library for materials analysis.\n",
"* [plotly](https://plotly.com/) : A platform for publishing beautiful, interactive graphs from Python to the web."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Firstly, we import numpy and pymatgen tools"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"from pymatgen.io.vaspio.vasp_output import Vasprun # read vasprun.xml output file of VASP\n",
"from pymatgen.electronic_structure.core import Spin"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we import plotly tools"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import plotly.plotly as pltly # plotting functions\n",
"import plotly.tools as tls # plotly tools\n",
"import plotly.graph_objs as go # plot and configuration tools : Scatter, Line, Layout"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Band Diagram and Denisty of States of Silicon"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1) Plot the density of states"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, read projected density of states (DOS) from a VASP calculation on ``\"./DOS/vasprun.xml\"`` file using pymatgen."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"dosrun = Vasprun(\"./DOS/vasprun.xml\")\n",
"spd_dos = dosrun.complete_dos.get_spd_dos()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Set up the scatter plots for the total DOS and the contribution of 3s and 3p atomic orbital to the total DOS."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# total DOS\n",
"trace_tdos = go.Scatter(\n",
" x=dosrun.tdos.densities[Spin.up],\n",
" y=dosrun.tdos.energies - dosrun.efermi,\n",
" mode=\"lines\",\n",
" name=\"total DOS\",\n",
" line=go.Line(color=\"#444444\"),\n",
" fill=\"tozeroy\"\n",
")\n",
"# 3s contribution to the total DOS\n",
"trace_3s = go.Scatter(\n",
" x=spd_dos[\"S\"].densities[Spin.up],\n",
" y=dosrun.tdos.energies - dosrun.efermi,\n",
" mode=\"lines\",\n",
" name=\"3s\",\n",
" line=go.Line(color=\"red\")\n",
")\n",
"# 3p contribution to the total DOS\n",
"trace_3p = go.Scatter(\n",
" x=spd_dos[\"P\"].densities[Spin.up],\n",
" y=dosrun.tdos.energies - dosrun.efermi,\n",
" mode=\"lines\",\n",
" name=\"3p\",\n",
" line=go.Line(color=\"green\")\n",
")\n",
"dosdata = go.Data([trace_tdos, trace_3s, trace_3p])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Customize axes and general aspect of the plot."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"dosxaxis = go.XAxis(\n",
" title=\"Density of states\",\n",
" showgrid=True,\n",
" showline=True,\n",
" range=[.01, 3],\n",
" mirror=\"ticks\",\n",
" ticks=\"inside\",\n",
" linewidth=2,\n",
" tickwidth=2\n",
")\n",
"dosyaxis = go.YAxis(\n",
" title=\"$E - E_f \\quad / \\quad \\\\text{eV}$\",\n",
" showgrid=True,\n",
" showline=True,\n",
" ticks=\"inside\",\n",
" mirror='ticks',\n",
" linewidth=2,\n",
" tickwidth=2,\n",
" zerolinewidth=2\n",
")\n",
"doslayout = go.Layout(\n",
" title=\"Density of states of Silicon\",\n",
" xaxis=dosxaxis,\n",
" yaxis=dosyaxis\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dosfig = go.Figure(data=dosdata, layout=doslayout)\n",
"plot_url = pltly.plot(dosfig, filename=\"DOS_Si\", auto_open=False)\n",
"tls.embed(plot_url)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2) Plot the band diagram"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, read bands from a VASP calculation on ``\"./Bandes/vasprun.xml\"`` file using pymatgen."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"run = Vasprun(\"./Bandes/vasprun.xml\", parse_projected_eigen = True)\n",
"bands = run.get_band_structure(\"./Bandes/KPOINTS\", line_mode=True, efermi=dosrun.efermi)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Look for the boundaries of the band diagram in order to set up y axes range."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"emin = 1e100\n",
"emax = -1e100\n",
"for spin in bands.bands.keys():\n",
" for band in range(bands.nb_bands):\n",
" emin = min(emin, min(bands.bands[spin][band]))\n",
" emax = max(emax, max(bands.bands[spin][band]))\n",
"emin = emin - bands.efermi - 1\n",
"emax = emax - bands.efermi + 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each band is plotted using a scatter plot."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"kptslist = [k for k in range(len(bands.kpoints))]\n",
"bandTraces = list()\n",
"for band in range(bands.nb_bands):\n",
" bandTraces.append(\n",
" go.Scatter(\n",
" x=kptslist,\n",
" y=[e - bands.efermi for e in bands.bands[Spin.up][band]],\n",
" mode=\"lines\",\n",
" line=go.Line(color=\"#666666\"),\n",
" showlegend=False\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add vertical lines at each high symmetry k-points and a label at the bottom."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"labels = [r\"$L$\", r\"$\\Gamma$\", r\"$X$\", r\"$U,K$\", r\"$\\Gamma$\"]\n",
"step = len(bands.kpoints) / (len(labels) - 1)\n",
"# vertical lines\n",
"vlines = list()\n",
"for i, label in enumerate(labels):\n",
" vlines.append(\n",
" go.Scatter(\n",
" x=[i * step, i * step],\n",
" y=[emin, emax],\n",
" mode=\"lines\",\n",
" line=go.Line(color=\"#111111\", width=1),\n",
" showlegend=False\n",
" )\n",
" )\n",
"# Labels of highsymetry k-points are added as Annotation object\n",
"annotations = list()\n",
"for i, label in enumerate(labels):\n",
" annotations.append(\n",
" go.Annotation(\n",
" x=i * step, y=emin,\n",
" xref=\"x1\", yref=\"y1\",\n",
" text=label,\n",
" xanchor=\"center\", yanchor=\"top\",\n",
" showarrow=False\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Customize axes and general aspect of the plot."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"bandxaxis = go.XAxis(\n",
" title=\"k-points\",\n",
" range=[0, len(bands.kpoints)],\n",
" showgrid=True,\n",
" showline=True,\n",
" ticks=\"\", \n",
" showticklabels=False,\n",
" mirror=True,\n",
" linewidth=2\n",
")\n",
"bandyaxis = go.YAxis(\n",
" title=\"$E - E_f \\quad / \\quad \\\\text{eV}$\",\n",
" range=[emin, emax],\n",
" showgrid=True,\n",
" showline=True,\n",
" zeroline=True,\n",
" mirror=\"ticks\",\n",
" ticks=\"inside\",\n",
" linewidth=2,\n",
" tickwidth=2,\n",
" zerolinewidth=2\n",
")\n",
"bandlayout = go.Layout(\n",
" title=\"Bands diagram of Silicon\",\n",
" xaxis=bandxaxis,\n",
" yaxis=bandyaxis,\n",
" annotations=go.Annotations(annotations)\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bandfig = go.Figure(data=bandTraces + vlines, layout=bandlayout)\n",
"plot_url = pltly.plot(bandfig, filename=\"Bands_Si\", auto_open=False)\n",
"tls.embed(plot_url)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3) Use subplots to plot DOS and bands together"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now make a figure with both the band diagram and the density of states using the ``make_subplots`` facility. First, we set up a figure with two columns, one row. At the end, the two plots will share y axis."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This is the format of your plot grid:\n",
"[ (1,1) x1,y1 ] [ (1,2) x2,y1 ]\n",
"\n"
]
}
],
"source": [
"dosbandfig = tls.make_subplots(rows=1, cols=2, shared_yaxes=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We use the previously defined traces for the band and the densities of state and add them to the figure object.\n",
"\n",
"* The bands are plotted on the left subplot (1, 1)\n",
"* The densities of states are plotted on the right subplot (1, 2)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# add the bands\n",
"for btrace in bandTraces:\n",
" dosbandfig.append_trace(btrace, 1, 1)\n",
"# add vlines for specific k-points\n",
"for vline in vlines:\n",
" dosbandfig.append_trace(vline, 1, 1)\n",
"# add the densities\n",
"dosbandfig.append_trace(trace_tdos, 1, 2)\n",
"dosbandfig.append_trace(trace_3s, 1, 2)\n",
"dosbandfig.append_trace(trace_3p, 1, 2) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Customize axes and general aspect of the plot using previously defined axis and layout options. The ``\"domain\"`` of each subplot is also define."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"dosbandfig[\"layout\"].update(\n",
" go.Layout(\n",
" title=\"Bands diagram and density of states of Silicon\",\n",
" xaxis1=bandxaxis,\n",
" yaxis1=bandyaxis,\n",
" xaxis2=dosxaxis,\n",
" annotations=go.Annotations(annotations)\n",
" )\n",
")\n",
"# adjust size of subplots\n",
"dosbandfig[\"layout\"][\"xaxis1\"][\"domain\"] = [0., 0.7]\n",
"dosbandfig[\"layout\"][\"xaxis2\"][\"domain\"] = [0.702, 1.]\n",
"# add some specific options\n",
"dosbandfig[\"layout\"][\"yaxis1\"][\"mirror\"] = \"allticks\"\n",
"dosbandfig[\"layout\"][\"xaxis2\"][\"mirror\"] = \"allticks\""
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"plot_url = pltly.plot(dosbandfig, filename=\"DOS_bands_Si\", auto_open=False)\n",
"tls.embed(plot_url)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4) Atomic orbital contributions in bands using a color scale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As previously done for the density of states, the contribution of 3s and 3p atomic orbital may be highlighted using a color scale. The main idea, from [this example](https://github.com/vossjo/ase-espresso/wiki/Band-structure-calculation-example), is to normalize atomic orbital contributions and build the RGB code of the color from these contributions.\n",
"\n",
"Thus, we first compute atomic orbital normalized contributions from projected bands :"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# extract projected bands\n",
"name = \"Si\"\n",
"pbands = bands.get_projections_on_elts_and_orbitals({name: [\"s\", \"p\", \"d\"]})\n",
"\n",
"# compute contributions\n",
"contrib = np.zeros((bands.nb_bands, len(bands.kpoints), 3)) \n",
"for band in range(bands.nb_bands):\n",
" for k in range(len(bands.kpoints)):\n",
" sc = pbands[Spin.up][band][k][name][\"s\"]**2\n",
" pc = pbands[Spin.up][band][k][name][\"p\"]**2\n",
" dc = pbands[Spin.up][band][k][name][\"d\"]**2\n",
" tot = sc + pc + dc\n",
" if tot != 0.0:\n",
" contrib[band, k, 0] = sc / tot\n",
" contrib[band, k, 1] = pc / tot\n",
" contrib[band, k, 2] = dc / tot"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now for each band, for each couple of consecutive points, we plot a line plot with a specific color, defined from the atomic orbital contributions to the current band."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"colorBands = list() # will contain the list of all lines\n",
"nkpts = len(bands.kpoints)\n",
"for band in range(bands.nb_bands):\n",
" eband = [e - bands.efermi for e in bands.bands[Spin.up][band]]\n",
" for k in range(nkpts - 1):\n",
" red, green, blue = [int(255 * (contrib[band, k, i] + contrib[band, k+1, i])/2) for i in range(3)]\n",
" colorBands.append(\n",
" go.Scatter(\n",
" x=[k, k+1],\n",
" y=[eband[k], eband[k+1]],\n",
" mode=\"lines\",\n",
" line=go.Line(color=\"rgb({}, {}, {})\".format(red, green, blue)),\n",
" showlegend=False\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As previously, two subplots are used to plot the band diagram on the left and the density of states on the right."
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This is the format of your plot grid:\n",
"[ (1,1) x1,y1 ] [ (1,2) x2,y1 ]\n",
"\n"
]
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# set up a new figure with two subplots\n",
"colorbandfig = tls.make_subplots(rows=1, cols=2, shared_yaxes=True)\n",
"# add the bands in the first subplot\n",
"for btrace in colorBands:\n",
" colorbandfig.append_trace(btrace, 1, 1)\n",
"# add vlines for specific k-points in the first subplot\n",
"for vline in vlines:\n",
" colorbandfig.append_trace(vline, 1, 1)\n",
"# add the densities in the second subplot\n",
"colorbandfig.append_trace(trace_tdos, 1, 2)\n",
"colorbandfig.append_trace(trace_3s, 1, 2)\n",
"colorbandfig.append_trace(trace_3p, 1, 2)\n",
"# Layout configuration\n",
"colorbandfig[\"layout\"].update(\n",
" go.Layout(\n",
" title=\"Bands diagram and density of states of Silicon\",\n",
" xaxis1=bandxaxis,\n",
" yaxis1=bandyaxis,\n",
" xaxis2=dosxaxis,\n",
" annotations=go.Annotations(annotations)\n",
" )\n",
")\n",
"# adjust size of subplots\n",
"colorbandfig[\"layout\"][\"xaxis1\"][\"domain\"] = [0., 0.7]\n",
"colorbandfig[\"layout\"][\"xaxis2\"][\"domain\"] = [0.702, 1.]\n",
"# add some specific options\n",
"colorbandfig[\"layout\"][\"yaxis1\"][\"mirror\"] = \"allticks\"\n",
"colorbandfig[\"layout\"][\"xaxis2\"][\"mirror\"] = \"allticks\"\n",
"# add a custom legend\n",
"legend = go.Legend(\n",
" x=.98, y=.98,\n",
" xanchor=\"right\", yanchor=\"top\",\n",
" bordercolor='#333', borderwidth=1\n",
")\n",
"colorbandfig[\"layout\"][\"legend\"] = legend\n",
"# do the plot\n",
"plot_url = pltly.plot(colorbandfig, filename=\"DOS_bands_Si_color\", auto_open=False)\n",
"tls.embed(plot_url)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import HTML, display\n",
"\n",
"display(HTML(''))\n",
"display(HTML(''))\n",
"\n",
"import publisher\n",
"publisher.publish('density-of-states ', '/ipython-notebooks/density-of-states/', \n",
" 'plotting the density of states and the band diagram using pymatgen and plotly', \n",
" 'Plotting Density of States with Plotly and Pymatgen')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}