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"""
2Output support for X3D and X3DOM file types.
3See http://www.web3d.org/x3d/specifications/
4X3DOM outputs to html pages that should display 3-d manipulatable atoms in
5modern web browsers.
6"""
8from ase.data import covalent_radii
9from ase.data.colors import jmol_colors
10from ase.utils import writer
13@writer
14def write_x3d(fd, atoms, format='X3D'):
15 """Writes to html using X3DOM.
17 Args:
18 filename - str or file-like object, filename or output file object
19 atoms - Atoms object to be rendered
20 format - str, either 'X3DOM' for web-browser compatibility or 'X3D'
21 to be readable by Blender. `None` to detect format based on file
22 extension ('.html' -> 'X3DOM', '.x3d' -> 'X3D')"""
23 X3D(atoms).write(fd, datatype=format)
26@writer
27def write_html(fd, atoms):
28 """Writes to html using X3DOM.
30 Args:
31 filename - str or file-like object, filename or output file object
32 atoms - Atoms object to be rendered"""
33 write_x3d(fd, atoms, format='X3DOM')
36class X3D:
37 """Class to write either X3D (readable by open-source rendering
38 programs such as Blender) or X3DOM html, readable by modern web
39 browsers.
40 """
42 def __init__(self, atoms):
43 self._atoms = atoms
45 def write(self, fileobj, datatype):
46 """Writes output to either an 'X3D' or an 'X3DOM' file, based on
47 the extension. For X3D, filename should end in '.x3d'. For X3DOM,
48 filename should end in '.html'.
50 Args:
51 datatype - str, output format. 'X3D' or 'X3DOM'.
52 """
54 # Write the header
55 w = WriteToFile(fileobj)
56 if datatype == 'X3DOM':
57 w(0, '<html>')
58 w(1, '<head>')
59 w(2, '<title>ASE atomic visualization</title>')
60 w(2, '<link rel="stylesheet" type="text/css"')
61 w(2, ' href="https://www.x3dom.org/x3dom/release/x3dom.css">')
62 w(2, '</link>')
63 w(2, '<script type="text/javascript"')
64 w(2, ' src="https://www.x3dom.org/x3dom/release/x3dom.js">')
65 w(2, '</script>')
66 w(1, '</head>')
67 w(1, '<body>')
68 w(2, '<X3D>')
69 elif datatype == 'X3D':
70 w(0, '<?xml version="1.0" encoding="UTF-8"?>')
71 w(0, '<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.2//EN" '
72 '"http://www.web3d.org/specifications/x3d-3.2.dtd">')
73 w(0, '<X3D profile="Interchange" version="3.2" '
74 'xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" '
75 'xsd:noNamespaceSchemaLocation='
76 '"http://www.web3d.org/specifications/x3d-3.2.xsd">')
77 else:
78 raise ValueError("datatype not supported: " + str(datatype))
80 w(3, '<Scene>')
82 for atom in self._atoms:
83 for indent, line in atom_lines(atom):
84 w(4 + indent, line)
86 w(3, '</Scene>')
88 if datatype == 'X3DOM':
89 w(2, '</X3D>')
90 w(1, '</body>')
91 w(0, '</html>')
92 elif datatype == 'X3D':
93 w(0, '</X3D>')
96class WriteToFile:
97 """Creates convenience function to write to a file."""
99 def __init__(self, fileobj):
100 self._f = fileobj
102 def __call__(self, indent, line):
103 text = ' ' * indent
104 print('%s%s\n' % (text, line), file=self._f)
107def atom_lines(atom):
108 """Generates a segment of X3D lines representing an atom."""
109 x, y, z = atom.position
110 lines = [(0, '<Transform translation="%.2f %.2f %.2f">' % (x, y, z))]
111 lines += [(1, '<Shape>')]
112 lines += [(2, '<Appearance>')]
113 color = tuple(jmol_colors[atom.number])
114 color = 'diffuseColor="%.3f %.3f %.3f"' % color
115 lines += [(3, '<Material %s specularColor="0.5 0.5 0.5">' % color)]
116 lines += [(3, '</Material>')]
117 lines += [(2, '</Appearance>')]
118 lines += [(2, '<Sphere radius="%.2f">' % covalent_radii[atom.number])]
119 lines += [(2, '</Sphere>')]
120 lines += [(1, '</Shape>')]
121 lines += [(0, '</Transform>')]
122 return lines