{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualize Orbitals" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import exatomic\n", "from exatomic.base import resource # Easy access to static files\n", "from exatomic import UniverseWidget as UW # The visualization system" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quantum chemistry codes don't always make it easy to get all the necessary information but provided the outputs have the data and the parser is implemented to handle the print-out from a specific code, this is what the API looks like for orbital viewing.\n", "- First you parse the output \n", " - must contain full basis set specification and a matrix of basis function coefficients\n", " \n", "```\n", "ed = exatomic.myqmcode.Output('/path/to/my/output')\n", "```\n", "\n", "- Inspect the parsed data. Does it look correct?\n", "\n", "```\n", "ed.basis_set # houses primitive exponents, coefficients\n", "ed.momatrix # contains the basis function coefficients\n", "ed.basis_set_order # indices specifying full basis set order\n", "```\n", "- `ed` is an Editor, an object that makes parsing files fun!\n", " - `ed` must be converted to a universe for the magic to happen\n", "\n", "```\n", "uni = ed.to_universe()\n", "```\n", "- A Universe has an add_molecular_orbitals method\n", "\n", "```\n", "uni.add_molecular_orbitals? # to see all keyword arguments\n", "uni.add_molecular_orbitals() # tries to guess smart defaults\n", "```\n", "\n", "- Don't forget python uses 0-based indexing, so check your vector values!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gaussian API" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "scrolled": true }, "outputs": [], "source": [ "from exatomic import gaussian\n", "\n", "uni = gaussian.Output(resource('g09-ch3nh2-631g.out')).to_universe()\n", "fni = gaussian.Fchk(resource('g09-ch3nh2-631g.fchk')).to_universe()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
setZxyzframesymbol
atom
0060.1002571.3462170.0000000C
1170.100257-1.4316660.0000000N
221-1.8473132.0168180.0000000H
3211.0740432.0168201.6866450H
4211.0740432.016820-1.6866450H
521-0.802058-2.053050-1.5628560H
621-0.802058-2.0530501.5628560H
\n", "
" ], "text/plain": [ "Atom(7, 7)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "uni.atom # Inspect the geometry" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
centerLmlshellframe
chi
000000
100010
201130
301-130
401030
\n", "
" ], "text/plain": [ "DataFrame(5, 5)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "uni.basis_set_order.head() # And the first few basis functions" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating 28 basis functions once.\n", "Timing: compute orbitals - 2.81s.\n", "Evaluating 28 basis functions once.\n", "Timing: compute orbitals - 0.37s.\n" ] } ], "source": [ "# Let's add the first 10 molecular orbitals \n", "uni.add_molecular_orbitals(vector=range(10))\n", "fni.add_molecular_orbitals(vector=range(10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### The UniverseWidget accepts up to 9 universes\n", "\n", "- Play around with the buttons:\n", " - Clear removes contents from the scene. (Press Fill to get the geometry back)\n", " - Active Scenes controls which scenes are controlled by the buttons (default all)\n", " - Image allows for saving PNGs of the scenes (can specify a directory and file names)\n", " - Camera allows to link the camera between scenes (load and save are buggy)\n", " - Fill switches between WebGL fragment shaders and fancy three.js Spheres\n", " - Axis adds a unit axis (often hidden within an atom if centered at the origin)\n", " - Animate will play dynamics (if a universe has multiple frames)\n", " - Fields expands to show:\n", " - Isosurfaces tab shows the molecular orbitals\n", " - Contours tab shows contour lines in x, y, or z axes\n", "- Be sure to use the close button to clean up the javascript side of things" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "4b906934e9fe4cffb35734660ddc9af6", "version_major": 2, "version_minor": 0 }, "text/plain": [ "A Jupyter Widget" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "UW(uni, fni)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Recursive solid harmonics means no hard-coded maximum angular momentum" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating 141 basis functions once.\n", "Timing: compute orbitals - 1.06s.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c1542cc1148c4873a0a67c863c8cf98f", "version_major": 2, "version_minor": 0 }, "text/plain": [ "A Jupyter Widget" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "uo2 = gaussian.Output(resource('g09-uo2.out')).to_universe()\n", "uo2.add_molecular_orbitals()\n", "UW(uo2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Molcas API\n", "- You must include the `BSSHOW` keyword in the `SEWARD` module or `GATEWAY` with a higher than normal print threshold to print the basis set specification\n", "- Molcas prints out Orb files which contain basis function coefficients so we use 2 `Editors`" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from exatomic import molcas\n", "\n", "mol = molcas.Output(resource('mol-uo2-anomb.out'))\n", "orb = molcas.Orb(resource('mol-uo2-anomb.scforb'))\n", "# Just attach it to the universe\n", "# mol.momatrix = orb.momatrix\n", "# mol.orbital = orb.orbital\n", "\n", "# Alternatively there's a convenience method on molcas.Output\n", "mol.add_orb(resource('mol-uo2-anomb.scforb')) # adds momatrix and orbital\n", "uni = mol.to_universe()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating 69 basis functions once.\n", "Timing: compute orbitals - 3.37s.\n" ] } ], "source": [ "uni.add_molecular_orbitals(vector=range(40, 60))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2d94bdf030534b66941d7828f8bb6b9d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "A Jupyter Widget" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "UW(uni)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### NWChem API" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from exatomic import nwchem\n", "\n", "nw = nwchem.Output(resource('nw-ch3nh2-631g.out')).to_universe()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating 28 basis functions once.\n", "Timing: compute orbitals - 0.43s.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "6b8fb8e39b834cc6bee4311454e2fdf5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "A Jupyter Widget" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "nw.add_molecular_orbitals(vector=range(20))\n", "UW(nw)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- If you are interested in helping, that's great!\n", "\n", "- The Editor objects deal with file IO and contain parse_methods specific to each dataframe.\n", "\n", "- In order to add_molecular_orbitals, the Editor must parse the Atom, BasisSet, BasisSetOrder and MOMatrix dataframes.\n", "\n", "- The requirements for these dataframes are specified in their docstrings.\n", "\n", "- The actual interface with the widget occurs on the Universe object, so the Editor must be converted to a Universe.\n", "\n", "- Therefore, it makes sense to subclass the exatomic.Editor to gain access to the .to_universe() method.\n", "\n", "- Keep parse_dataframe methods modular if possible to isolate problems when they arise." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1" } }, "nbformat": 4, "nbformat_minor": 4 }