Coverage for cclib/bridge/cclib2openbabel.py : 89%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2017, the cclib development team
4#
5# This file is part of cclib (http://cclib.github.io) and is distributed under
6# the terms of the BSD 3-Clause License.
8"""Bridge between cclib data and openbabel (http://openbabel.org)."""
10from cclib.parser.data import ccData
11from cclib.parser.utils import find_package
13_found_openbabel = find_package("openbabel")
14if _found_openbabel:
15 # The exception idiom is needed because OB < 3.0 doesn't set __version__.
16 # The `try` block is for OB >= 3.0, and `except` is for 2.4.x and older.
17 try:
18 from openbabel import openbabel as ob
19 except:
20 import openbabel as ob
23def _check_openbabel(found_openbabel):
24 if not found_openbabel:
25 raise ImportError("You must install `openbabel` to use this function")
28def makecclib(mol):
29 """Create cclib attributes and return a ccData from an OpenBabel molecule.
31 Beyond the numbers, masses and coordinates, we could also set the total charge
32 and multiplicity, but often these are calculated from atomic formal charges
33 so it is better to assume that would not be correct.
34 """
35 _check_openbabel(_found_openbabel)
36 attributes = {
37 'atomcoords': [],
38 'atommasses': [],
39 'atomnos': [],
40 'natom': mol.NumAtoms(),
41 }
42 for atom in ob.OBMolAtomIter(mol):
43 attributes['atomcoords'].append([atom.GetX(), atom.GetY(), atom.GetZ()])
44 attributes['atommasses'].append(atom.GetAtomicMass())
45 attributes['atomnos'].append(atom.GetAtomicNum())
46 attributes['atomcoords'] = [attributes['atomcoords']]
47 return ccData(attributes)
50def makeopenbabel(atomcoords, atomnos, charge=0, mult=1):
51 """Create an Open Babel molecule."""
52 _check_openbabel(_found_openbabel)
53 obmol = ob.OBMol()
54 for i in range(len(atomnos)):
55 # Note that list(atomcoords[i]) is not equivalent!!!
56 # For now, only take the last geometry.
57 # TODO: option to export last geometry or all geometries?
58 coords = atomcoords[-1][i].tolist()
59 atomno = int(atomnos[i])
60 obatom = ob.OBAtom()
61 obatom.SetAtomicNum(atomno)
62 obatom.SetVector(*coords)
63 obmol.AddAtom(obatom)
64 obmol.ConnectTheDots()
65 obmol.PerceiveBondOrders()
66 obmol.SetTotalSpinMultiplicity(mult)
67 obmol.SetTotalCharge(int(charge))
68 return obmol
71def readfile(fname, format):
72 """Read a file with OpenBabel and extract cclib attributes."""
73 _check_openbabel(_found_openbabel)
74 obc = ob.OBConversion()
75 if obc.SetInFormat(format):
76 mol = ob.OBMol()
77 obc.ReadFile(mol, fname)
78 return makecclib(mol)
79 else:
80 print("Unable to load the %s reader from OpenBabel." % format)
81 return {}
84del find_package