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

1import json 

2import numpy as np 

3 

4import ase.units as units 

5from ase import Atoms 

6from ase.data import chemical_symbols 

7 

8 

9nomad_api_template = ('https://labdev-nomad.esc.rzg.mpg.de/' 

10 'api/resolve/{hash}?format=recursiveJson') 

11 

12 

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:]) 

17 

18 

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 

25 

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)) 

30 

31 

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. 

37 

38 def hook(dct): 

39 d = {k: dct[k] for k in dct if _includekeys(k)} 

40 return NomadEntry(d) 

41 

42 dct = json.load(fd, object_hook=hook) 

43 return dct 

44 

45 

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'] 

57 

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 

65 

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 

72 

73 return atoms 

74 

75 

76def nomad_entry_to_images(section): 

77 """Yield the images from a Nomad entry. 

78 

79 The entry must contain a section_run. 

80 One atoms object will be yielded for each section_system.""" 

81 

82 

83class NomadEntry(dict): 

84 """An entry from the Nomad database. 

85 

86 The Nomad entry is represented as nested dictionaries and lists. 

87 

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) 

96 

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:] 

102 

103 def toatoms(self): 

104 """Convert this NomadEntry into an Atoms object. 

105 

106 This NomadEntry must represent a section_system.""" 

107 return section_system_to_atoms(self) 

108 

109 def iterimages(self): 

110 """Yield Atoms object contained within this NomadEntry. 

111 

112 This NomadEntry must represent or contain a section_run.""" 

113 

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 

119 

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'] 

126 

127 if self.get('name') == 'calculation_context': 

128 atoms.info['nomad_calculation_uri'] = self['uri'] 

129 yield atoms 

130 

131 

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())) 

138 

139 

140if __name__ == '__main__': 

141 main()