{
"metadata": {
"name": "",
"signature": "sha256:e3e16318ef005448635d5e2e1f3a481f8911e81fd14ff6d53a749c4fe26d60f1"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Band Diagram and Denisty of States of Silicon"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"with Plotly's Python API library and PyMatgen"
]
},
{
"cell_type": "heading",
"level": 6,
"metadata": {},
"source": [
"Germain Salvato-Vallverdu (germain.vallverdu@univ-pau.fr)"
]
},
{
"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://plot.ly/) packages.\n",
"\n",
"* [pymatgen](http://pymatgen.org/) : (Python Materials Genomics) A robust, open-source Python library for materials analysis.\n",
"* [plotly](https://plot.ly/) : A platform for publishing beautiful, interactive graphs from Python to the web."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "heading",
"level": 3,
"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",
"collapsed": true,
"input": [
"dosrun = Vasprun(\"./DOS/vasprun.xml\")\n",
"spd_dos = dosrun.complete_dos.get_spd_dos()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"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",
"collapsed": false,
"input": [
"# 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])"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Customize axes and general aspect of the plot."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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",
")"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"dosfig = go.Figure(data=dosdata, layout=doslayout)\n",
"plot_url = pltly.plot(dosfig, filename=\"DOS_Si\", auto_open=False)\n",
"tls.embed(plot_url)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
""
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
""
]
}
],
"prompt_number": 6
},
{
"cell_type": "heading",
"level": 3,
"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",
"collapsed": false,
"input": [
"run = Vasprun(\"./Bandes/vasprun.xml\", parse_projected_eigen = True)\n",
"bands = run.get_band_structure(\"./Bandes/KPOINTS\", line_mode=True, efermi=dosrun.efermi)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Look for the boundaries of the band diagram in order to set up y axes range."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each band is plotted using a scatter plot."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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",
" )"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 20
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add vertical lines at each high symmetry k-points and a label at the bottom."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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",
" )"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 21
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Customize axes and general aspect of the plot."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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",
")"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 22
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"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)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
""
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 24,
"text": [
""
]
}
],
"prompt_number": 24
},
{
"cell_type": "heading",
"level": 3,
"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",
"collapsed": false,
"input": [
"dosbandfig = tls.make_subplots(rows=1, cols=2, shared_yaxes=True)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the format of your plot grid:\n",
"[ (1,1) x1,y1 ] [ (1,2) x2,y1 ]\n",
"\n"
]
}
],
"prompt_number": 25
},
{
"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",
"collapsed": false,
"input": [
"# 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) "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 26
},
{
"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",
"collapsed": false,
"input": [
"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\""
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 27
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"plot_url = pltly.plot(dosbandfig, filename=\"DOS_bands_Si\", auto_open=False)\n",
"tls.embed(plot_url)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
""
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 28,
"text": [
""
]
}
],
"prompt_number": 28
},
{
"cell_type": "heading",
"level": 3,
"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",
"collapsed": false,
"input": [
"# 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"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 29
},
{
"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",
"collapsed": false,
"input": [
"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",
" )"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 30
},
{
"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",
"collapsed": false,
"input": [
"# 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)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the format of your plot grid:\n",
"[ (1,1) x1,y1 ] [ (1,2) x2,y1 ]\n",
"\n"
]
},
{
"html": [
""
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 31,
"text": [
""
]
}
],
"prompt_number": 31
}
],
"metadata": {}
}
]
}