Visualize Orbitals
[1]:
import exatomic
from exatomic.base import resource # Easy access to static files
from exatomic import UniverseWidget as UW # The visualization system
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. - First you parse the output - must contain full basis set specification and a matrix of basis function coefficients
ed = exatomic.myqmcode.Output('/path/to/my/output')
Inspect the parsed data. Does it look correct?
ed.basis_set # houses primitive exponents, coefficients
ed.momatrix # contains the basis function coefficients
ed.basis_set_order # indices specifying full basis set order
ed
is an Editor, an object that makes parsing files fun!ed
must be converted to a universe for the magic to happen
uni = ed.to_universe()
A Universe has an add_molecular_orbitals method
uni.add_molecular_orbitals? # to see all keyword arguments
uni.add_molecular_orbitals() # tries to guess smart defaults
Don’t forget python uses 0-based indexing, so check your vector values!
Gaussian API
[2]:
from exatomic import gaussian
uni = gaussian.Output(resource('g09-ch3nh2-631g.out')).to_universe()
fni = gaussian.Fchk(resource('g09-ch3nh2-631g.fchk')).to_universe()
[3]:
uni.atom # Inspect the geometry
[3]:
set | Z | x | y | z | frame | symbol | |
---|---|---|---|---|---|---|---|
atom | |||||||
0 | 0 | 6 | 0.100257 | 1.346217 | 0.000000 | 0 | C |
1 | 1 | 7 | 0.100257 | -1.431666 | 0.000000 | 0 | N |
2 | 2 | 1 | -1.847313 | 2.016818 | 0.000000 | 0 | H |
3 | 2 | 1 | 1.074043 | 2.016820 | 1.686645 | 0 | H |
4 | 2 | 1 | 1.074043 | 2.016820 | -1.686645 | 0 | H |
5 | 2 | 1 | -0.802058 | -2.053050 | -1.562856 | 0 | H |
6 | 2 | 1 | -0.802058 | -2.053050 | 1.562856 | 0 | H |
[4]:
uni.basis_set_order.head() # And the first few basis functions
[4]:
center | L | ml | shell | frame | |
---|---|---|---|---|---|
chi | |||||
0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 1 | 0 |
2 | 0 | 1 | 1 | 3 | 0 |
3 | 0 | 1 | -1 | 3 | 0 |
4 | 0 | 1 | 0 | 3 | 0 |
[5]:
# Let's add the first 10 molecular orbitals
uni.add_molecular_orbitals(vector=range(10))
fni.add_molecular_orbitals(vector=range(10))
Evaluating 28 basis functions once.
Timing: compute orbitals - 2.81s.
Evaluating 28 basis functions once.
Timing: compute orbitals - 0.37s.
The UniverseWidget accepts up to 9 universes
Play around with the buttons:
Clear removes contents from the scene. (Press Fill to get the geometry back)
Active Scenes controls which scenes are controlled by the buttons (default all)
Image allows for saving PNGs of the scenes (can specify a directory and file names)
Camera allows to link the camera between scenes (load and save are buggy)
Fill switches between WebGL fragment shaders and fancy three.js Spheres
Axis adds a unit axis (often hidden within an atom if centered at the origin)
Animate will play dynamics (if a universe has multiple frames)
Fields expands to show:
Isosurfaces tab shows the molecular orbitals
Contours tab shows contour lines in x, y, or z axes
Be sure to use the close button to clean up the javascript side of things
[6]:
UW(uni, fni)
Recursive solid harmonics means no hard-coded maximum angular momentum
[7]:
uo2 = gaussian.Output(resource('g09-uo2.out')).to_universe()
uo2.add_molecular_orbitals()
UW(uo2)
Evaluating 141 basis functions once.
Timing: compute orbitals - 1.06s.
Molcas API
You must include the
BSSHOW
keyword in theSEWARD
module orGATEWAY
with a higher than normal print threshold to print the basis set specificationMolcas prints out Orb files which contain basis function coefficients so we use 2
Editors
[8]:
from exatomic import molcas
mol = molcas.Output(resource('mol-uo2-anomb.out'))
orb = molcas.Orb(resource('mol-uo2-anomb.scforb'))
# Just attach it to the universe
# mol.momatrix = orb.momatrix
# mol.orbital = orb.orbital
# Alternatively there's a convenience method on molcas.Output
mol.add_orb(resource('mol-uo2-anomb.scforb')) # adds momatrix and orbital
uni = mol.to_universe()
[9]:
uni.add_molecular_orbitals(vector=range(40, 60))
Evaluating 69 basis functions once.
Timing: compute orbitals - 3.37s.
[10]:
UW(uni)
NWChem API
[11]:
from exatomic import nwchem
nw = nwchem.Output(resource('nw-ch3nh2-631g.out')).to_universe()
[12]:
nw.add_molecular_orbitals(vector=range(20))
UW(nw)
Evaluating 28 basis functions once.
Timing: compute orbitals - 0.43s.
If you are interested in helping, that’s great!
The Editor objects deal with file IO and contain parse_methods specific to each dataframe.
In order to add_molecular_orbitals, the Editor must parse the Atom, BasisSet, BasisSetOrder and MOMatrix dataframes.
The requirements for these dataframes are specified in their docstrings.
The actual interface with the widget occurs on the Universe object, so the Editor must be converted to a Universe.
Therefore, it makes sense to subclass the exatomic.Editor to gain access to the .to_universe() method.
Keep parse_dataframe methods modular if possible to isolate problems when they arise.
[ ]: