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"Module for displaying information about the system." 

2 

3 

4import numpy as np 

5from ase.gui.i18n import _ 

6import warnings 

7 

8 

9ucellformat = """\ 

10 {:8.3f} {:8.3f} {:8.3f} 

11 {:8.3f} {:8.3f} {:8.3f} 

12 {:8.3f} {:8.3f} {:8.3f} 

13""" 

14 

15 

16def info(gui): 

17 images = gui.images 

18 nimg = len(images) 

19 atoms = gui.atoms 

20 

21 tokens = [] 

22 

23 def add(token=''): 

24 tokens.append(token) 

25 

26 if len(atoms) < 1: 

27 add(_('This frame has no atoms.')) 

28 else: 

29 img = gui.frame 

30 

31 if nimg == 1: 

32 add(_('Single image loaded.')) 

33 else: 

34 add(_('Image {} loaded (0–{}).').format(img, nimg - 1)) 

35 add() 

36 add(_('Number of atoms: {}').format(len(atoms))) 

37 

38 # We need to write ų further down, so we have no choice but to 

39 # use proper subscripts in the chemical formula: 

40 formula = atoms.get_chemical_formula() 

41 subscripts = dict(zip('0123456789', '₀₁₂₃₄₅₆₇₈₉')) 

42 pretty_formula = ''.join(subscripts.get(c, c) for c in formula) 

43 add(pretty_formula) 

44 

45 add() 

46 add(_('Unit cell [Å]:')) 

47 add(ucellformat.format(*atoms.cell.ravel())) 

48 periodic = [[_('no'), _('yes')][int(periodic)] 

49 for periodic in atoms.pbc] 

50 # TRANSLATORS: This has the form Periodic: no, no, yes 

51 add(_('Periodic: {}, {}, {}').format(*periodic)) 

52 add() 

53 

54 cellpar = atoms.cell.cellpar() 

55 add() 

56 add(_('Lengths [Å]: {:.3f}, {:.3f}, {:.3f}').format(*cellpar[:3])) 

57 add(_('Angles: {:.1f}°, {:.1f}°, {:.1f}°').format(*cellpar[3:])) 

58 

59 if atoms.cell.rank == 3: 

60 add(_('Volume: {:.3f} ų').format(atoms.cell.volume)) 

61 

62 add() 

63 

64 if nimg > 1: 

65 if all((atoms.cell == img.cell).all() for img in images): 

66 add(_('Unit cell is fixed.')) 

67 else: 

68 add(_('Unit cell varies.')) 

69 

70 if atoms.pbc[:2].all() and atoms.cell.rank >= 1: 

71 try: 

72 lat = atoms.cell.get_bravais_lattice() 

73 except RuntimeError: 

74 add(_('Could not recognize the lattice type')) 

75 except Exception: 

76 add(_('Unexpected error determining lattice type')) 

77 else: 

78 add(_('Reduced Bravais lattice:\n{}').format(lat)) 

79 

80 # Print electronic structure information if we have a calculator 

81 if atoms.calc: 

82 calc = atoms.calc 

83 

84 def getresult(name, get_quantity): 

85 # ase/io/trajectory.py line 170 does this by using 

86 # the get_property(prop, atoms, allow_calculation=False) 

87 # so that is an alternative option. 

88 try: 

89 if calc.calculation_required(atoms, [name]): 

90 quantity = None 

91 else: 

92 quantity = get_quantity() 

93 except Exception as err: 

94 quantity = None 

95 errmsg = ('An error occurred while retrieving {} ' 

96 'from the calculator: {}'.format(name, err)) 

97 warnings.warn(errmsg) 

98 return quantity 

99 

100 # SinglePointCalculators are named after the code which 

101 # produced the result, so this will typically list the 

102 # name of a code even if they are just cached results. 

103 add() 

104 from ase.calculators.singlepoint import SinglePointCalculator 

105 if isinstance(calc, SinglePointCalculator): 

106 add(_('Calculator: {} (cached)').format(calc.name)) 

107 else: 

108 add(_('Calculator: {} (attached)').format(calc.name)) 

109 

110 energy = getresult('energy', atoms.get_potential_energy) 

111 forces = getresult('forces', atoms.get_forces) 

112 magmom = getresult('magmom', atoms.get_magnetic_moment) 

113 

114 if energy is not None: 

115 energy_str = _('Energy: {:.3f} eV').format(energy) 

116 add(energy_str) 

117 

118 if forces is not None: 

119 maxf = np.linalg.norm(forces, axis=1).max() 

120 forces_str = _('Max force: {:.3f} eV/Å').format(maxf) 

121 add(forces_str) 

122 

123 if magmom is not None: 

124 mag_str = _('Magmom: {:.3f} µ').format(magmom) 

125 add(mag_str) 

126 

127 return '\n'.join(tokens)