From 2e530b44c49e0ab8ae21688e8b57539c2096d983 Mon Sep 17 00:00:00 2001 From: __sp__ Date: Fri, 12 Sep 2014 08:34:16 -0700 Subject: [PATCH] Fixes for openbabel parsing and output. Revamped examples for basic functionality in Structures and Molecules. Former-commit-id: e6cf14a18884d6ada8ab972bd4fddf6f858d5510 [formerly a95ff35954df9baac3bd7010440f2e7e333baefb] Former-commit-id: 9d08d83b76fc56a24f83e62eec2ab4adb6fd09d2 --- examples/Basic functionality.ipynb | 119 +++++++++++++++++++++----- examples/Molecule.ipynb | 130 ++++++++++++++++++++++++----- pymatgen/core/structure.py | 12 ++- pymatgen/core/units.py | 1 - pymatgen/io/babelio.py | 2 +- 5 files changed, 211 insertions(+), 53 deletions(-) diff --git a/examples/Basic functionality.ipynb b/examples/Basic functionality.ipynb index 3170c19a5ce..b38b06f2c62 100644 --- a/examples/Basic functionality.ipynb +++ b/examples/Basic functionality.ipynb @@ -1,6 +1,7 @@ { "metadata": { - "name": "" + "name": "", + "signature": "sha256:22c38efd64283402a562a1901d5f0c4f35a9d052e62861db275c1a0fb73e0f68" }, "nbformat": 3, "nbformat_minor": 0, @@ -55,9 +56,9 @@ "collapsed": false, "input": [ "si = mg.Element(\"Si\")\n", - "print \"Atomic mass of Si is {}\".format(si.atomic_mass)\n", - "print \"Si has a melting point of {}\".format(si.melting_point)\n", - "print \"Ionic radii for Si: {}\".format(si.ionic_radii)" + "print(\"Atomic mass of Si is {}\".format(si.atomic_mass))\n", + "print(\"Si has a melting point of {}\".format(si.melting_point))\n", + "print(\"Ionic radii for Si: {}\".format(si.ionic_radii))" ], "language": "python", "metadata": {}, @@ -85,7 +86,7 @@ "cell_type": "code", "collapsed": false, "input": [ - "print \"Atomic mass of Si in kg: {}\".format(si.atomic_mass.to(\"kg\"))" + "print(\"Atomic mass of Si in kg: {}\".format(si.atomic_mass.to(\"kg\")))" ], "language": "python", "metadata": {}, @@ -112,8 +113,8 @@ "collapsed": false, "input": [ "fe2 = mg.Specie(\"Fe\", 2)\n", - "print fe2.atomic_mass\n", - "print fe2.ionic_radius" + "print(fe2.atomic_mass)\n", + "print(fe2.ionic_radius)" ], "language": "python", "metadata": {}, @@ -141,10 +142,10 @@ "collapsed": false, "input": [ "comp = mg.Composition(\"Fe2O3\")\n", - "print \"Weight of Fe2O3 is {}\".format(comp.weight)\n", - "print \"Amount of Fe in Fe2O3 is {}\".format(comp[\"Fe\"])\n", - "print \"Atomic fraction of Fe is {}\".format(comp.get_atomic_fraction(\"Fe\"))\n", - "print \"Weight fraction of Fe is {}\".format(comp.get_wt_fraction(\"Fe\"))" + "print(\"Weight of Fe2O3 is {}\".format(comp.weight))\n", + "print(\"Amount of Fe in Fe2O3 is {}\".format(comp[\"Fe\"]))\n", + "print(\"Atomic fraction of Fe is {}\".format(comp.get_atomic_fraction(\"Fe\")))\n", + "print(\"Weight fraction of Fe is {}\".format(comp.get_wt_fraction(\"Fe\")))" ], "language": "python", "metadata": {}, @@ -183,7 +184,7 @@ "input": [ "# Creates cubic Lattice with lattice parameter 4.2\n", "lattice = mg.Lattice.cubic(4.2)\n", - "print lattice.lengths_and_angles" + "print(lattice.lengths_and_angles)" ], "language": "python", "metadata": {}, @@ -210,8 +211,8 @@ "collapsed": false, "input": [ "structure = mg.Structure(lattice, [\"Cs\", \"Cl\"], [[0, 0, 0], [0.5, 0.5, 0.5]])\n", - "print \"Unit cell vol = {}\".format(structure.volume)\n", - "print \"First site of the structure is {}\".format(structure[0])" + "print(\"Unit cell vol = {}\".format(structure.volume))\n", + "print(\"First site of the structure is {}\".format(structure[0]))" ], "language": "python", "metadata": {}, @@ -244,7 +245,7 @@ "structure[-1] = \"Li\" #Change the last added atom to Li.\n", "structure[0] = \"Cs\", [0.01, 0.5, 0] #Shift the first atom by 0.01 in fractional coordinates in the x-direction.\n", "immutable_structure = mg.IStructure.from_sites(structure) #Create an immutable structure (cannot be modified).\n", - "print immutable_structure" + "print(immutable_structure)" ], "language": "python", "metadata": {}, @@ -293,7 +294,7 @@ "#Determining the symmetry\n", "from pymatgen.symmetry.finder import SymmetryFinder\n", "finder = SymmetryFinder(structure)\n", - "print \"The spacegroup is {}\".format(finder.get_spacegroup_symbol())" + "print(\"The spacegroup is {}\".format(finder.get_spacegroup_symbol()))" ], "language": "python", "metadata": {}, @@ -324,7 +325,7 @@ "s1 = mg.Structure(lattice, [\"Cs\", \"Cl\"], [[0, 0, 0], [0.5, 0.5, 0.5]])\n", "s2 = mg.Structure(mg.Lattice.cubic(5), [\"Rb\", \"F\"], [[0, 0, 0], [0.5, 0.5, 0.5]])\n", "m = StructureMatcher()\n", - "print m.fit_anonymous(s1, s2) #Returns a mapping which maps s1 and s2 onto each other. Strict element fitting is also available." + "print(m.fit_anonymous(s1, s2)) #Returns a mapping which maps s1 and s2 onto each other. Strict element fitting is also available." ], "language": "python", "metadata": {}, @@ -333,7 +334,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "{Comp: Cl1: Comp: F1, Comp: Cs1: Comp: Rb1}\n" + "True\n" ] } ], @@ -359,16 +360,88 @@ "collapsed": false, "input": [ "#Convenient IO to various formats. Format is intelligently determined from file name and extension.\n", - "mg.write_structure(structure, \"POSCAR\")\n", - "mg.write_structure(structure, \"CsCl.cif\")\n", + "structure.to(filename=\"POSCAR\")\n", + "structure.to(filename=\"CsCl.cif\")\n", "\n", + "#Or if you just supply fmt, you simply get a string.\n", + "print(structure.to(fmt=\"poscar\"))\n", + "print(structure.to(fmt=\"cif\"))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Cs3 Li1 Cl4\n", + "1.0\n", + "8.400000 0.000000 0.000000\n", + "0.000000 8.400000 0.000000\n", + "0.000000 0.000000 4.200000\n", + "Cs Cl Li\n", + "3 4 1\n", + "direct\n", + "0.010000 0.500000 0.000000 Cs\n", + "0.500000 0.000000 0.000000 Cs\n", + "0.500000 0.500000 0.000000 Cs\n", + "0.250000 0.250000 0.500000 Cl\n", + "0.250000 0.750000 0.500000 Cl\n", + "0.750000 0.250000 0.500000 Cl\n", + "0.750000 0.750000 0.500000 Cl\n", + "0.000000 0.000000 0.000000 Li\n", + "\n", + "#generated using pymatgen\n", + "data_Cs3LiCl4\n", + "_symmetry_space_group_name_H-M 'P 1'\n", + "_cell_length_a 8.40000000\n", + "_cell_length_b 8.40000000\n", + "_cell_length_c 4.20000000\n", + "_cell_angle_alpha 90.00000000\n", + "_cell_angle_beta 90.00000000\n", + "_cell_angle_gamma 90.00000000\n", + "_symmetry_Int_Tables_number 1\n", + "_chemical_formula_structural Cs3LiCl4\n", + "_chemical_formula_sum 'Cs3 Li1 Cl4'\n", + "_cell_volume 296.352\n", + "_cell_formula_units_Z 1\n", + "loop_\n", + " _symmetry_equiv_pos_site_id\n", + " _symmetry_equiv_pos_as_xyz\n", + " 1 'x, y, z'\n", + "loop_\n", + " _atom_site_type_symbol\n", + " _atom_site_label\n", + " _atom_site_symmetry_multiplicity\n", + " _atom_site_fract_x\n", + " _atom_site_fract_y\n", + " _atom_site_fract_z\n", + " _atom_site_occupancy\n", + " Cs Cs1 1 0.010000 0.500000 0.000000 1\n", + " Cs Cs2 1 0.500000 0.000000 0.000000 1\n", + " Cs Cs3 1 0.500000 0.500000 0.000000 1\n", + " Cl Cl4 1 0.250000 0.250000 0.500000 1\n", + " Cl Cl5 1 0.250000 0.750000 0.500000 1\n", + " Cl Cl6 1 0.750000 0.250000 0.500000 1\n", + " Cl Cl7 1 0.750000 0.750000 0.500000 1\n", + " Li Li8 1 0.000000 0.000000 0.000000 1\n", + "\n" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ "#Reading a structure from a file.\n", - "structure = mg.read_structure(\"POSCAR\")" + "structure = mg.Structure.from_file(\"POSCAR\")" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 11 + "prompt_number": 12 }, { "cell_type": "markdown", @@ -388,7 +461,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 12 + "prompt_number": 13 }, { "cell_type": "heading", diff --git a/examples/Molecule.ipynb b/examples/Molecule.ipynb index c307516fb3c..387cf183bd8 100644 --- a/examples/Molecule.ipynb +++ b/examples/Molecule.ipynb @@ -1,6 +1,7 @@ { "metadata": { - "name": "" + "name": "", + "signature": "sha256:e2cf45fce91cabfcc6574401a7be0eb65d87d0f79ebb4a7681e717c48c79d611" }, "nbformat": 3, "nbformat_minor": 0, @@ -42,7 +43,7 @@ " [-0.513360, -0.889165, -0.363000],\n", " [-0.513360, 0.889165, -0.363000]]\n", "mol = Molecule([\"C\", \"H\", \"H\", \"H\", \"H\"], coords)\n", - "print mol" + "print(mol)" ], "language": "python", "metadata": {}, @@ -70,8 +71,8 @@ "collapsed": false, "input": [ "# A Molecule is simply a list of Sites.\n", - "print mol[0]\n", - "print mol[1]" + "print(mol[0])\n", + "print(mol[1])" ], "language": "python", "metadata": {}, @@ -93,7 +94,7 @@ "input": [ "# Break a Molecule into two by breaking a bond.\n", "for frag in mol.break_bond(0, 1):\n", - " print frag" + " print(frag)" ], "language": "python", "metadata": {}, @@ -125,7 +126,7 @@ "collapsed": false, "input": [ "# Getting neighbors that are within 3 angstroms from C atom.\n", - "print mol.get_neighbors(mol[0], 3)" + "print(mol.get_neighbors(mol[0], 3))" ], "language": "python", "metadata": {}, @@ -145,7 +146,7 @@ "collapsed": false, "input": [ "#Detecting bonds\n", - "print mol.get_covalent_bonds()" + "print(mol.get_covalent_bonds())" ], "language": "python", "metadata": {}, @@ -167,7 +168,7 @@ "# If you need to run the molecule in a box with a periodic boundary condition\n", "# code, you can generate the boxed structure as follows (in a 10Ax10Ax10A box)\n", "structure = mol.get_boxed_structure(10, 10, 10)\n", - "print structure" + "print(structure)" ], "language": "python", "metadata": {}, @@ -230,9 +231,9 @@ "# Create a pybel.Molecule, which simplifies a lot of access\n", "pm = pb.Molecule(a.openbabel_mol)\n", "# Print canonical SMILES representation (unique and comparable).\n", - "print \"Canonical SMILES = {}\".format(pm.write(\"can\"))\n", + "print(\"Canonical SMILES = {}\".format(pm.write(\"can\")))\n", "# Print Inchi representation\n", - "print \"Inchi= {}\".format(pm.write(\"inchi\"))\n", + "print(\"Inchi= {}\".format(pm.write(\"inchi\")))\n", "# pb.outformats provides a listing of available formats. \n", "# Let's do a write to the commonly used PDB file.\n", "pm.write(\"pdb\", filename=\"methane.pdb\", overwrite=True)" @@ -316,7 +317,94 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Pymatgen has built-in support for Gaussian and Nwchem, two commonly used computational chemistry programs." + "Pymatgen has built-in support for the XYZ and Gaussian, NWchem file formats. It also has support for most other file formats if you have openbabel with Python bindings installed." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(mol.to(fmt=\"xyz\"))\n", + "print(mol.to(fmt=\"g09\"))\n", + "print(mol.to(fmt=\"pdb\")) #Needs Openbabel.\n", + "\n", + "mol.to(filename=\"methane.xyz\")\n", + "mol.to(filename=\"methane.pdb\") #Needs Openbabel.\n", + "\n", + "print(Molecule.from_file(\"methane.pdb\"))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "5\n", + "H4 C1\n", + "C 0.000000 0.000000 0.000000\n", + "H 0.000000 0.000000 1.089000\n", + "H 1.026719 0.000000 -0.363000\n", + "H -0.513360 -0.889165 -0.363000\n", + "H -0.513360 0.889165 -0.363000\n", + "#P HF/6-31G(d) Test\n", + "\n", + "H4 C1\n", + "\n", + "0 1\n", + "C\n", + "H 1 B1\n", + "H 1 B2 2 A2\n", + "H 1 B3 2 A3 3 D3\n", + "H 1 B4 2 A4 4 D4\n", + "\n", + "B1=1.089000\n", + "B2=1.089000\n", + "A2=109.471221\n", + "B3=1.089000\n", + "A3=109.471213\n", + "D3=120.000017\n", + "B4=1.089000\n", + "A4=109.471213\n", + "D4=119.999966\n", + "\n", + "\n", + "\n", + "COMPND UNNAMED\n", + "AUTHOR GENERATED BY OPEN BABEL 2.3.2\n", + "HETATM 1 C LIG 1 0.000 0.000 0.000 1.00 0.00 C \n", + "HETATM 2 H LIG 1 0.000 0.000 1.089 1.00 0.00 H \n", + "HETATM 3 H LIG 1 1.027 0.000 -0.363 1.00 0.00 H \n", + "HETATM 4 H LIG 1 -0.513 -0.889 -0.363 1.00 0.00 H \n", + "HETATM 5 H LIG 1 -0.513 0.889 -0.363 1.00 0.00 H \n", + "CONECT 1 3 4 5 2 \n", + "CONECT 1 \n", + "CONECT 2 1 \n", + "CONECT 3 1 \n", + "CONECT 4 1 \n", + "CONECT 5 1 \n", + "MASTER 0 0 0 0 0 0 0 0 5 0 5 0\n", + "END\n", + "\n", + "Molecule Summary (H4 C1)\n", + "Reduced Formula: H4C\n", + "Charge = 0, Spin Mult = 1\n", + "Sites (5)\n", + "1 C 0.000000 0.000000 0.000000\n", + "2 H 0.000000 0.000000 1.089000\n", + "3 H 1.027000 0.000000 -0.363000\n", + "4 H -0.513000 -0.889000 -0.363000\n", + "5 H -0.513000 0.889000 -0.363000\n" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For more fine-grained control over output, you can use the underlying IO classes Gaussian and Nwchem, two commonly used computational chemistry programs." ] }, { @@ -328,7 +416,7 @@ " functional=\"B3LYP\", basis_set=\"6-31G(d)\", \n", " route_parameters={'Opt': \"\", \"SCF\": \"Tight\"},\n", " link0_parameters={\"%mem\": \"1000MW\"})\n", - "print gau" + "print(gau)" ], "language": "python", "metadata": {}, @@ -364,7 +452,7 @@ ] } ], - "prompt_number": 10 + "prompt_number": 11 }, { "cell_type": "code", @@ -381,7 +469,7 @@ " basis_set=\"6-311G\"),\n", "]\n", "nwi = NwInput(mol, tasks, geometry_options=[\"units\", \"angstroms\"])\n", - "print nwi" + "print(nwi)" ], "language": "python", "metadata": {}, @@ -401,43 +489,43 @@ "title \"H4C1 dft optimize\"\n", "charge 0\n", "basis\n", - " H library \"6-31G\"\n", " C library \"6-31G\"\n", + " H library \"6-31G\"\n", "end\n", "dft\n", - " xc b3lyp\n", " mult 1\n", + " xc b3lyp\n", "end\n", "task dft optimize\n", "\n", "title \"H4C1 dft freq\"\n", "charge 0\n", "basis\n", - " H library \"6-31G\"\n", " C library \"6-31G\"\n", + " H library \"6-31G\"\n", "end\n", "dft\n", - " xc b3lyp\n", " mult 1\n", + " xc b3lyp\n", "end\n", "task dft freq\n", "\n", "title \"H4C1 dft energy\"\n", "charge 0\n", "basis\n", - " H library \"6-311G\"\n", " C library \"6-311G\"\n", + " H library \"6-311G\"\n", "end\n", "dft\n", - " xc b3lyp\n", " mult 1\n", + " xc b3lyp\n", "end\n", "task dft energy\n", "\n" ] } ], - "prompt_number": 11 + "prompt_number": 12 }, { "cell_type": "heading", diff --git a/pymatgen/core/structure.py b/pymatgen/core/structure.py index 83b61ba6dd1..35058483a6e 100644 --- a/pymatgen/core/structure.py +++ b/pymatgen/core/structure.py @@ -4,8 +4,6 @@ """ from __future__ import division -from six.moves import map -from six.moves import zip __author__ = "Shyue Ping Ong" __copyright__ = "Copyright 2011, The Materials Project" @@ -30,6 +28,7 @@ import numpy as np import six +from six.moves import map, zip from fractions import gcd from pymatgen.core.operations import SymmOp @@ -1566,10 +1565,8 @@ def to(self, fmt=None, filename=None): from pymatgen.io.gaussianio import GaussianInput from pymatgen.io.babelio import BabelMolAdaptor - filename = filename or "" fmt = "" if fmt is None else fmt.lower() - fname = os.path.basename(filename) - + fname = os.path.basename(filename or "") if fmt == "xyz" or fnmatch(fname.lower(), "*.xyz*"): writer = XYZ(self) elif any([fmt == r or fnmatch(fname.lower(), "*.{}*".format(r)) @@ -1584,10 +1581,11 @@ def to(self, fmt=None, filename=None): return json.dumps(self.as_dict()) else: m = re.search("\.(pdb|mol|mdl|sdf|sd|ml2|sy2|mol2|cml|mrv)", - filename.lower()) + fname.lower()) if (not fmt) and m: fmt = m.group(1) - writer = BabelMolAdaptor(self, fmt) + writer = BabelMolAdaptor(self) + return writer.write_file(filename, file_format=fmt) if filename: writer.write_file(filename) diff --git a/pymatgen/core/units.py b/pymatgen/core/units.py index c94347e855d..24395bc0d74 100644 --- a/pymatgen/core/units.py +++ b/pymatgen/core/units.py @@ -326,7 +326,6 @@ def __init__(self, val, unit, unit_type=None): def __repr__(self): return super(FloatWithUnit, self).__repr__() - #return "{} {}".format(s, self._unit) def __str__(self): s = super(FloatWithUnit, self).__str__() diff --git a/pymatgen/io/babelio.py b/pymatgen/io/babelio.py index 8890fa092a6..057b6462ac7 100644 --- a/pymatgen/io/babelio.py +++ b/pymatgen/io/babelio.py @@ -123,7 +123,7 @@ def write_file(self, filename, file_format="xyz"): file_format: String specifying any OpenBabel supported formats. """ mol = pb.Molecule(self._obmol) - mol.write(file_format, filename, overwrite=True) + return mol.write(file_format, filename, overwrite=True) @staticmethod def from_file(filename, file_format="xyz"):