Hide keyboard shortcuts

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. 

7 

8"""Bridge between cclib data and openbabel (http://openbabel.org).""" 

9 

10from cclib.parser.data import ccData 

11from cclib.parser.utils import find_package 

12 

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 

21 

22 

23def _check_openbabel(found_openbabel): 

24 if not found_openbabel: 

25 raise ImportError("You must install `openbabel` to use this function") 

26 

27 

28def makecclib(mol): 

29 """Create cclib attributes and return a ccData from an OpenBabel molecule. 

30 

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) 

48 

49 

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 

69 

70 

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 {} 

82 

83 

84del find_package