1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
"Module for displaying information about the system."
import numpy as np
from ase.gui.i18n import _
import warnings
ucellformat = """\
{:8.3f} {:8.3f} {:8.3f}
{:8.3f} {:8.3f} {:8.3f}
{:8.3f} {:8.3f} {:8.3f}
"""
def info(gui):
images = gui.images
nimg = len(images)
atoms = gui.atoms
tokens = []
def add(token=''):
tokens.append(token)
if len(atoms) < 1:
add(_('This frame has no atoms.'))
else:
img = gui.frame
if nimg == 1:
add(_('Single image loaded.'))
else:
add(_('Image {} loaded (0–{}).').format(img, nimg - 1))
add()
add(_('Number of atoms: {}').format(len(atoms)))
# We need to write ų further down, so we have no choice but to
# use proper subscripts in the chemical formula:
formula = atoms.get_chemical_formula()
subscripts = dict(zip('0123456789', '₀₁₂₃₄₅₆₇₈₉'))
pretty_formula = ''.join(subscripts.get(c, c) for c in formula)
add(pretty_formula)
add()
add(_('Unit cell [Å]:'))
add(ucellformat.format(*atoms.cell.ravel()))
periodic = [[_('no'), _('yes')][int(periodic)]
for periodic in atoms.pbc]
# TRANSLATORS: This has the form Periodic: no, no, yes
add(_('Periodic: {}, {}, {}').format(*periodic))
add()
cellpar = atoms.cell.cellpar()
add()
add(_('Lengths [Å]: {:.3f}, {:.3f}, {:.3f}').format(*cellpar[:3]))
add(_('Angles: {:.1f}°, {:.1f}°, {:.1f}°').format(*cellpar[3:]))
if atoms.cell.rank == 3:
add(_('Volume: {:.3f} ų').format(atoms.cell.volume))
add()
if nimg > 1:
if all((atoms.cell == img.cell).all() for img in images):
add(_('Unit cell is fixed.'))
else:
add(_('Unit cell varies.'))
if atoms.pbc[:2].all() and atoms.cell.rank >= 1:
try:
lat = atoms.cell.get_bravais_lattice()
except RuntimeError:
add(_('Could not recognize the lattice type'))
except Exception:
add(_('Unexpected error determining lattice type'))
else:
add(_('Reduced Bravais lattice:\n{}').format(lat))
# Print electronic structure information if we have a calculator
if atoms.calc:
calc = atoms.calc
def getresult(name, get_quantity):
# ase/io/trajectory.py line 170 does this by using
# the get_property(prop, atoms, allow_calculation=False)
# so that is an alternative option.
try:
if calc.calculation_required(atoms, [name]):
quantity = None
else:
quantity = get_quantity()
except Exception as err:
quantity = None
errmsg = ('An error occurred while retrieving {} '
'from the calculator: {}'.format(name, err))
warnings.warn(errmsg)
return quantity
# SinglePointCalculators are named after the code which
# produced the result, so this will typically list the
# name of a code even if they are just cached results.
add()
from ase.calculators.singlepoint import SinglePointCalculator
if isinstance(calc, SinglePointCalculator):
add(_('Calculator: {} (cached)').format(calc.name))
else:
add(_('Calculator: {} (attached)').format(calc.name))
energy = getresult('energy', atoms.get_potential_energy)
forces = getresult('forces', atoms.get_forces)
magmom = getresult('magmom', atoms.get_magnetic_moment)
if energy is not None:
energy_str = _('Energy: {:.3f} eV').format(energy)
add(energy_str)
if forces is not None:
maxf = np.linalg.norm(forces, axis=1).max()
forces_str = _('Max force: {:.3f} eV/Å').format(maxf)
add(forces_str)
if magmom is not None:
mag_str = _('Magmom: {:.3f} µ').format(magmom)
add(mag_str)
return '\n'.join(tokens)
|