Statistiques
| Révision :

root / ase / io / eps.py @ 1

Historique | Voir | Annoter | Télécharger (6,04 ko)

1 1 tkerber
import time
2 1 tkerber
from math import sqrt
3 1 tkerber
4 1 tkerber
import numpy as np
5 1 tkerber
6 1 tkerber
from ase.utils import rotate
7 1 tkerber
from ase.data import covalent_radii
8 1 tkerber
from ase.data.colors import jmol_colors
9 1 tkerber
10 1 tkerber
11 1 tkerber
class EPS:
12 1 tkerber
    def __init__(self, atoms,
13 1 tkerber
                 rotation='', show_unit_cell=False, radii=None,
14 1 tkerber
                 bbox=None, colors=None, scale=20):
15 1 tkerber
        self.numbers = atoms.get_atomic_numbers()
16 1 tkerber
        self.colors = colors
17 1 tkerber
        if colors is None:
18 1 tkerber
            self.colors = jmol_colors[self.numbers]
19 1 tkerber
20 1 tkerber
        if radii is None:
21 1 tkerber
            radii = covalent_radii[self.numbers]
22 1 tkerber
        elif type(radii) is float:
23 1 tkerber
            radii = covalent_radii[self.numbers] * radii
24 1 tkerber
25 1 tkerber
        natoms = len(atoms)
26 1 tkerber
27 1 tkerber
        if isinstance(rotation, str):
28 1 tkerber
            rotation = rotate(rotation)
29 1 tkerber
30 1 tkerber
        A = atoms.get_cell()
31 1 tkerber
        if show_unit_cell > 0:
32 1 tkerber
            L, T, D = self.cell_to_lines(A)
33 1 tkerber
            C = np.empty((2, 2, 2, 3))
34 1 tkerber
            for c1 in range(2):
35 1 tkerber
                for c2 in range(2):
36 1 tkerber
                    for c3 in range(2):
37 1 tkerber
                        C[c1, c2, c3] = np.dot([c1, c2, c3], A)
38 1 tkerber
            C.shape = (8, 3)
39 1 tkerber
            C = np.dot(C, rotation) # Unit cell vertices
40 1 tkerber
        else:
41 1 tkerber
            L = np.empty((0, 3))
42 1 tkerber
            T = None
43 1 tkerber
            D = None
44 1 tkerber
            C = None
45 1 tkerber
46 1 tkerber
        nlines = len(L)
47 1 tkerber
48 1 tkerber
        X = np.empty((natoms + nlines, 3))
49 1 tkerber
        R = atoms.get_positions()
50 1 tkerber
        X[:natoms] = R
51 1 tkerber
        X[natoms:] = L
52 1 tkerber
53 1 tkerber
        r2 = radii**2
54 1 tkerber
        for n in range(nlines):
55 1 tkerber
            d = D[T[n]]
56 1 tkerber
            if ((((R - L[n] - d)**2).sum(1) < r2) &
57 1 tkerber
                (((R - L[n] + d)**2).sum(1) < r2)).any():
58 1 tkerber
                T[n] = -1
59 1 tkerber
60 1 tkerber
        X = np.dot(X, rotation)
61 1 tkerber
        R = X[:natoms]
62 1 tkerber
63 1 tkerber
        if bbox is None:
64 1 tkerber
            X1 = (R - radii[:, None]).min(0)
65 1 tkerber
            X2 = (R + radii[:, None]).max(0)
66 1 tkerber
            if show_unit_cell == 2:
67 1 tkerber
                X1 = np.minimum(X1, C.min(0))
68 1 tkerber
                X2 = np.maximum(X2, C.max(0))
69 1 tkerber
            M = (X1 + X2) / 2
70 1 tkerber
            S = 1.05 * (X2 - X1)
71 1 tkerber
            w = scale * S[0]
72 1 tkerber
            if w > 500:
73 1 tkerber
                w = 500
74 1 tkerber
                scale = w / S[0]
75 1 tkerber
            h = scale * S[1]
76 1 tkerber
            offset = np.array([scale * M[0] - w / 2, scale * M[1] - h / 2, 0])
77 1 tkerber
        else:
78 1 tkerber
            w = (bbox[2] - bbox[0]) * scale
79 1 tkerber
            h = (bbox[3] - bbox[1]) * scale
80 1 tkerber
            offset = np.array([bbox[0], bbox[1], 0]) * scale
81 1 tkerber
82 1 tkerber
        self.w = w
83 1 tkerber
        self.h = h
84 1 tkerber
85 1 tkerber
        X *= scale
86 1 tkerber
        X -= offset
87 1 tkerber
88 1 tkerber
        if nlines > 0:
89 1 tkerber
            D = np.dot(D, rotation)[:, :2] * scale
90 1 tkerber
91 1 tkerber
        if C is not None:
92 1 tkerber
            C *= scale
93 1 tkerber
            C -= offset
94 1 tkerber
95 1 tkerber
        A = np.dot(A, rotation)
96 1 tkerber
        A *= scale
97 1 tkerber
98 1 tkerber
        self.A = A
99 1 tkerber
        self.X = X
100 1 tkerber
        self.D = D
101 1 tkerber
        self.T = T
102 1 tkerber
        self.C = C
103 1 tkerber
        self.natoms = natoms
104 1 tkerber
        self.d = 2 * scale * radii
105 1 tkerber
106 1 tkerber
    def cell_to_lines(self, A):
107 1 tkerber
        nlines = 0
108 1 tkerber
        nn = []
109 1 tkerber
        for c in range(3):
110 1 tkerber
            d = sqrt((A[c]**2).sum())
111 1 tkerber
            n = max(2, int(d / 0.3))
112 1 tkerber
            nn.append(n)
113 1 tkerber
            nlines += 4 * n
114 1 tkerber
115 1 tkerber
        X = np.empty((nlines, 3))
116 1 tkerber
        T = np.empty(nlines, int)
117 1 tkerber
        D = np.zeros((3, 3))
118 1 tkerber
119 1 tkerber
        n1 = 0
120 1 tkerber
        for c in range(3):
121 1 tkerber
            n = nn[c]
122 1 tkerber
            dd = A[c] / (4 * n - 2)
123 1 tkerber
            D[c] = dd
124 1 tkerber
            P = np.arange(1, 4 * n + 1, 4)[:, None] * dd
125 1 tkerber
            T[n1:] = c
126 1 tkerber
            for i, j in [(0, 0), (0, 1), (1, 0), (1, 1)]:
127 1 tkerber
                n2 = n1 + n
128 1 tkerber
                X[n1:n2] = P + i * A[(c + 1) % 3] + j * A[(c + 2) % 3]
129 1 tkerber
                n1 = n2
130 1 tkerber
131 1 tkerber
        return X, T, D
132 1 tkerber
133 1 tkerber
    def write(self, filename):
134 1 tkerber
        self.filename = filename
135 1 tkerber
        self.write_header()
136 1 tkerber
        self.write_body()
137 1 tkerber
        self.write_trailer()
138 1 tkerber
139 1 tkerber
    def write_header(self):
140 1 tkerber
        import matplotlib
141 1 tkerber
        if matplotlib.__version__ <= '0.8':
142 1 tkerber
            raise RuntimeError('Your version of matplotlib (%s) is too old' %
143 1 tkerber
                               matplotlib.__version__)
144 1 tkerber
145 1 tkerber
        from matplotlib.backends.backend_ps import RendererPS, \
146 1 tkerber
             GraphicsContextPS, psDefs
147 1 tkerber
148 1 tkerber
        self.fd = open(self.filename, 'w')
149 1 tkerber
        self.fd.write('%!PS-Adobe-3.0 EPSF-3.0\n')
150 1 tkerber
        self.fd.write('%%Creator: G2\n')
151 1 tkerber
        self.fd.write('%%CreationDate: %s\n' % time.ctime(time.time()))
152 1 tkerber
        self.fd.write('%%Orientation: portrait\n')
153 1 tkerber
        bbox = (0, 0, self.w, self.h)
154 1 tkerber
        self.fd.write('%%%%BoundingBox: %d %d %d %d\n' % bbox)
155 1 tkerber
        self.fd.write('%%EndComments\n')
156 1 tkerber
157 1 tkerber
        Ndict = len(psDefs)
158 1 tkerber
        self.fd.write('%%BeginProlog\n')
159 1 tkerber
        self.fd.write('/mpldict %d dict def\n' % Ndict)
160 1 tkerber
        self.fd.write('mpldict begin\n')
161 1 tkerber
        for d in psDefs:
162 1 tkerber
            d = d.strip()
163 1 tkerber
            for l in d.split('\n'):
164 1 tkerber
                self.fd.write(l.strip() + '\n')
165 1 tkerber
        self.fd.write('%%EndProlog\n')
166 1 tkerber
167 1 tkerber
        self.fd.write('mpldict begin\n')
168 1 tkerber
        self.fd.write('%d %d 0 0 clipbox\n' % (self.w, self.h))
169 1 tkerber
170 1 tkerber
        self.renderer = RendererPS(self.w, self.h, self.fd)
171 1 tkerber
172 1 tkerber
    def write_body(self):
173 1 tkerber
        try:
174 1 tkerber
            from matplotlib.path import Path
175 1 tkerber
        except ImportError:
176 1 tkerber
            Path = None
177 1 tkerber
            from matplotlib.patches import Circle, Polygon
178 1 tkerber
        else:
179 1 tkerber
            from matplotlib.patches import Circle, PathPatch
180 1 tkerber
181 1 tkerber
        indices = self.X[:, 2].argsort()
182 1 tkerber
        for a in indices:
183 1 tkerber
            xy = self.X[a, :2]
184 1 tkerber
            if a < self.natoms:
185 1 tkerber
                circle = Circle(xy, self.d[a] / 2, facecolor=self.colors[a])
186 1 tkerber
                circle.draw(self.renderer)
187 1 tkerber
            else:
188 1 tkerber
                a -= self.natoms
189 1 tkerber
                c = self.T[a]
190 1 tkerber
                if c != -1:
191 1 tkerber
                    hxy = self.D[c]
192 1 tkerber
                    if Path is None:
193 1 tkerber
                        line = Polygon((xy + hxy, xy - hxy))
194 1 tkerber
                    else:
195 1 tkerber
                        line = PathPatch(Path((xy + hxy, xy - hxy)))
196 1 tkerber
                    line.draw(self.renderer)
197 1 tkerber
198 1 tkerber
    def write_trailer(self):
199 1 tkerber
        self.fd.write('end\n')
200 1 tkerber
        self.fd.write('showpage\n')
201 1 tkerber
        self.fd.close()
202 1 tkerber
203 1 tkerber
204 1 tkerber
def write_eps(filename, atoms, **parameters):
205 1 tkerber
    if isinstance(atoms, list):
206 1 tkerber
        assert len(atoms) == 1
207 1 tkerber
        atoms = atoms[0]
208 1 tkerber
    EPS(atoms, **parameters).write(filename)