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
1import json
2import numpy as np
4import ase.units as units
5from ase import Atoms
6from ase.data import chemical_symbols
9nomad_api_template = ('https://labdev-nomad.esc.rzg.mpg.de/'
10 'api/resolve/{hash}?format=recursiveJson')
13def nmd2https(uri):
14 """Get https URI corresponding to given nmd:// URI."""
15 assert uri.startswith('nmd://')
16 return nomad_api_template.format(hash=uri[6:])
19def download(uri):
20 """Download data at nmd:// URI as a NomadEntry object."""
21 try:
22 from urllib2 import urlopen
23 except ImportError:
24 from urllib.request import urlopen
26 httpsuri = nmd2https(uri)
27 response = urlopen(httpsuri)
28 txt = response.read().decode('utf8')
29 return json.loads(txt, object_hook=lambda dct: NomadEntry(dct))
32def read(fd, _includekeys=lambda key: True):
33 """Read NomadEntry object from file."""
34 # _includekeys can be used to strip unnecessary keys out of a
35 # downloaded nomad file so its size is suitable for inclusion
36 # in the test suite.
38 def hook(dct):
39 d = {k: dct[k] for k in dct if _includekeys(k)}
40 return NomadEntry(d)
42 dct = json.load(fd, object_hook=hook)
43 return dct
46def section_system_to_atoms(section):
47 """Covnert section_system into an Atoms object."""
48 assert section['name'] == 'section_system'
49 numbers = section['atom_species']
50 numbers = np.array(numbers, int)
51 numbers[numbers < 0] = 0 # We don't support Z < 0
52 numbers[numbers >= len(chemical_symbols)] = 0
53 positions = section['atom_positions']['flatData']
54 positions = np.array(positions).reshape(-1, 3) * units.m
55 atoms = Atoms(numbers, positions=positions)
56 atoms.info['nomad_uri'] = section['uri']
58 pbc = section.get('configuration_periodic_dimensions')
59 if pbc is not None:
60 assert len(pbc) == 1
61 pbc = pbc[0] # it's a list??
62 pbc = pbc['flatData']
63 assert len(pbc) == 3
64 atoms.pbc = pbc
66 # celldisp?
67 cell = section.get('lattice_vectors')
68 if cell is not None:
69 cell = cell['flatData']
70 cell = np.array(cell).reshape(3, 3) * units.m
71 atoms.cell = cell
73 return atoms
76def nomad_entry_to_images(section):
77 """Yield the images from a Nomad entry.
79 The entry must contain a section_run.
80 One atoms object will be yielded for each section_system."""
83class NomadEntry(dict):
84 """An entry from the Nomad database.
86 The Nomad entry is represented as nested dictionaries and lists.
88 ASE converts each dictionary into a NomadEntry object which supports
89 different actions. Some actions are only available when the NomadEntry
90 represents a particular section."""
91 def __init__(self, dct):
92 #assert dct['type'] == 'nomad_calculation_2_0'
93 #assert dct['name'] == 'calculation_context'
94 # We could implement NomadEntries that represent sections.
95 dict.__init__(self, dct)
97 @property
98 def hash(self):
99 # The hash is a string, so not __hash__
100 assert self['uri'].startswith('nmd://')
101 return self['uri'][6:]
103 def toatoms(self):
104 """Convert this NomadEntry into an Atoms object.
106 This NomadEntry must represent a section_system."""
107 return section_system_to_atoms(self)
109 def iterimages(self):
110 """Yield Atoms object contained within this NomadEntry.
112 This NomadEntry must represent or contain a section_run."""
114 if 'section_run' in self:
115 run_sections = self['section_run']
116 else:
117 assert self['name'] == 'section_run'
118 run_sections = [self] # We assume that we are the section_run
120 for run in run_sections:
121 systems = run['section_system']
122 for system in systems:
123 atoms = section_system_to_atoms(system)
124 atoms.info['nomad_run_gIndex'] = run['gIndex']
125 atoms.info['nomad_system_gIndex'] = system['gIndex']
127 if self.get('name') == 'calculation_context':
128 atoms.info['nomad_calculation_uri'] = self['uri']
129 yield atoms
132def main():
133 uri = "nmd://N9Jqc1y-Bzf7sI1R9qhyyyoIosJDs/C74RJltyQeM9_WFuJYO49AR4gKuJ2"
134 print(nmd2https(uri))
135 entry = download(uri)
136 from ase.visualize import view
137 view(list(entry.iterimages()))
140if __name__ == '__main__':
141 main()