



As a chemist it is often useful to plot electronic orbitals. These are used to describe the wave function of electrons in atoms or molecules. Typically, these are output from electronic structure software in the form of a cube file, first developed by Gaussian. These files contain volumetric data for a given orbital on a three-dimensional grid.





There exist many applications to visualize cube files, such as



First off, we need a function to extract the data from the cube file. In the process, we will create the text for an XYZ file, a format also developed by Gaussian. The function OutForm is used here to mimic the printf function found in other programming languages.



OutForm[num_?NumericQ, width_Integer, ndig_Integer,

OptionsPattern[]] :=

Module[{mant, exp, val},

{mant, exp} = MantissaExponent[num];

mant = ToString[NumberForm[mant, {ndig, ndig}]];

exp = If[Sign[exp] == -1, "-", "+"] <> IntegerString[exp, 10, 2];

val = mant <> "E" <> exp;

StringJoin@PadLeft[Characters[val], width, " "]

];



ReadCube[cubeFileName_?StringQ] := Module[

{moltxt, nAtoms, lowerCorner, nx, ny, nz, xstep, ystep, zstep,

atoms, desc1, desc2, xyzText, cubeDat, xgrid, ygrid, zgrid,

dummy1, dummy2, atomicNumber, atomx, atomy, atomz, tmpString,

headerTxt,bohr2angstrom},

bohr2angstrom = 0.529177249;

moltxt = OpenRead[cubeFileName];

desc1 = Read[moltxt, String];

desc2 = Read[moltxt, String];

lowerCorner = {0, 0, 0};

{nAtoms, lowerCorner[[1]], lowerCorner[[2]], lowerCorner[[3]]} =

Read[moltxt, String] // ImportString[#, "Table"][[1]] &;

xyzText = ToString[nAtoms] <> "

";

xyzText = xyzText <> desc1 <> desc2 <> "

";

{nx, xstep, dummy1, dummy2} =

Read[moltxt, String] // ImportString[#, "Table"][[1]] &;

{ny, dummy1, ystep, dummy2} =

Read[moltxt, String] // ImportString[#, "Table"][[1]] &;

{nz, dummy1, dummy2, zstep} =

Read[moltxt, String] // ImportString[#, "Table"][[1]] &;

Do[

{atomicNumber, dummy1, atomx, atomy, atomz} =

Read[moltxt, String] // ImportString[#, "Table"][[1]] &;

xyzText = If[Sign[lowerCorner[[1]]] == 1,

xyzText <> ElementData[atomicNumber, "Abbreviation"] <>

OutForm[atomx, 17, 7] <> OutForm[atomy, 17, 7] <>

OutForm[atomz, 17, 7] <> "

",

xyzText <> ElementData[atomicNumber, "Abbreviation"] <>

OutForm[bohr2angstrom atomx, 17, 7] <>

OutForm[bohr2angstrom atomy, 17, 7] <>

OutForm[bohr2angstrom atomz, 17, 7] <> "

"];

, {nAtoms}];

cubeDat =

Partition[Partition[ReadList[moltxt, Number, nx ny nz], nz], ny];

Close[moltxt];

moltxt = OpenRead[cubeFileName];

headerTxt = Read[moltxt, Table[String, {2 + 4 + nAtoms}]];

Close[moltxt];

headerTxt = StringJoin@Riffle[headerTxt, "

"];

xgrid =

Range[lowerCorner[[1]], lowerCorner[[1]] + xstep (nx - 1), xstep];

ygrid =

Range[lowerCorner[[2]], lowerCorner[[2]] + ystep (ny - 1), ystep];

zgrid =

Range[lowerCorner[[3]], lowerCorner[[3]] + zstep (nz - 1), zstep];

{cubeDat, xgrid, ygrid, zgrid, xyzText, headerTxt}

];



If you need to create a cube file, then the following function can be used:

WriteCube[cubeFileName_?StringQ, headerTxt_?StringQ, cubeData_] :=

Module[{stream},

stream = OpenWrite[cubeFileName, FormatType -> FortranForm];

WriteString[stream, headerTxt, "

"];

Map[WriteString[stream, ##, "

"] & @@

Riffle[ScientificForm[#, {3, 4},

NumberFormat -> (Row[{#1, "E", If[#3 == "", "+00", #3],

"\t"}] &), NumberPadding -> {"", "0"},

NumberSigns -> {"-", " "}] & /@ #, "

", {7, -1, 7}] &,

cubeData, {2}];

Close[stream];]

Next we need the function to plot the orbital,

CubePlot[{cub_, xg_, yg_, zg_, xyz_}, plotopts : OptionsPattern[]] :=

Module[{xyzplot, bohr2picometer, datarange3D, pr},

bohr2picometer = 52.9177249;

datarange3D =

bohr2picometer {{xg[[1]], xg[[-1]]}, {yg[[1]],

yg[[-1]]}, {zg[[1]], zg[[-1]]}};

xyzplot = ImportString[xyz, "XYZ"];

Show[xyzplot,

ListContourPlot3D[Transpose[cub, {3, 2, 1}],

Evaluate[FilterRules[{plotopts}, Options[ListContourPlot3D]]],

Contours -> {-.02, .02}, ContourStyle -> {Blue, Red},

DataRange -> datarange3D, MeshStyle -> Gray,

Lighting -> {{"Ambient", White}}],

Evaluate[

FilterRules[{plotopts}, {ViewPoint, ViewVertical, ImageSize}]]]

];

Lets look at an example. First we need to read in a cube file, download this cube file and place it in your base directory:

{cubedata,xg,yg,zg,xyz,header}= ReadCube["cys-MO35.cube"]; Then plot it via CubePlot[{cubedata, xg, yg, zg, xyz}]

When I want to create a movie file, I want all the images to have exactly the same ViewAngle, ViewPoint, and ViewCenter. When you give these options to CubePlot, it feeds them directly to the Show function

vp = {ViewCenter -> {0.5, 0.5, 0.5},

ViewPoint -> {1.072, 0.665, -3.13},

ViewVertical -> {0.443, 0.2477, 1.527}};





CubePlot[{cubedata, xg, yg, zg, xyz}, vp]



Finally, you can also give any options that normally go to ListContourPlot3D CubePlot[{cubedata, xg, yg, zg, xyz}, vp,

ContourStyle -> {Texture[ExampleData[{"ColorTexture", "Vavona"}]],

Texture[ExampleData[{"ColorTexture", "Amboyna"}]]},

Contours -> {-.015, .015}]





Many thanks to Daniel Healion for the ReadCube and WriteCube functions. I am reposting this here from the Stackexchange Mathematica blog so that more people might see it. I'd be very happy to get some feedback on this plotting function. If anyone can use the function, let me know how it works out for you, and if you'd recommend any changes. If so, I can edit this post to have to most up-to-date version.As a chemist it is often useful to plot electronic orbitals. These are used to describe the wave function of electrons in atoms or molecules. Typically, these are output from electronic structure software in the form of a cube file, first developed by Gaussian. These files contain volumetric data for a given orbital on a three-dimensional grid.There exist many applications to visualize cube files, such as VMD or GaussView , but I wanted to take advantage of Mathematicas capability to easily combine graphics, as well as the ability to automate the process in order to efficiently create frames for a movie First off, we need a function to extract the data from the cube file. In the process, we will create the text for an XYZ file, a format also developed by Gaussian. The functionis used here to mimic the printf function found in other programming languages.If you need to create a cube file, then the following function can be used:Next we need the function to plot the orbital,Lets look at an example. First we need to read in a cube file, download this cube file and place it in your base directory: cys-MO35cube Then plot it viaWhen I want to create a movie file, I want all the images to have exactly the same, and. When you give these options to, it feeds them directly to thefunctionFinally, you can also give any options that normally go toMany thanks to Daniel Healion for theandfunctions.