Statistiques
| Révision :

root / ase / utils / __init__.py @ 1

Historique | Voir | Annoter | Télécharger (3,34 ko)

1
from math import sin, cos, radians, atan2, degrees
2

    
3
import numpy as np
4

    
5

    
6
class DevNull:
7
    def write(self, string): pass
8
    def flush(self): pass
9
    def tell(self): return 0
10
    def close(self): pass
11

    
12
devnull = DevNull()
13

    
14

    
15
def rotate(rotations, rotation=np.identity(3)):
16
    """Convert string of format '50x,-10y,120z' to a rotation matrix.
17

18
    Note that the order of rotation matters, i.e. '50x,40z' is different
19
    from '40z,50x'.
20
    """
21
        
22
    if rotations == '':
23
        return rotation.copy()
24
    
25
    for i, a in [('xyz'.index(s[-1]), radians(float(s[:-1])))
26
                 for s in rotations.split(',')]:
27
        s = sin(a)
28
        c = cos(a)
29
        if i == 0:
30
            rotation = np.dot(rotation, [( 1,  0,  0),
31
                                          ( 0,  c, s),
32
                                          ( 0,  -s,  c)])
33
        elif i == 1:
34
            rotation = np.dot(rotation, [( c,  0, -s),
35
                                          ( 0,  1,  0),
36
                                          ( s,  0,  c)])
37
        else:
38
            rotation = np.dot(rotation, [( c, s,  0),
39
                                          ( -s,  c,  0),
40
                                          ( 0,  0,  1)])
41
    return rotation
42

    
43

    
44
def givens(a, b):
45
    """Solve the equation system::
46

47
      [ c s]   [a]   [r]
48
      [    ] . [ ] = [ ]
49
      [-s c]   [b]   [0]
50
    """
51
    sgn = lambda x: cmp(x, 0)
52
    if b == 0:
53
        c = sgn(a)
54
        s = 0
55
        r = abs(a)
56
    elif abs(b) >= abs(a):
57
        cot = a / b
58
        u = sgn(b) * (1 + cot**2)**.5
59
        s = 1. / u
60
        c = s * cot
61
        r = b * u
62
    else:
63
        tan = b / a
64
        u = sgn(a) * (1 + tan**2)**.5
65
        c = 1. / u
66
        s = c * tan
67
        r = a * u
68
    return c, s, r
69

    
70

    
71
def irotate(rotation, initial=np.identity(3)):
72
    """Determine x, y, z rotation angles from rotation matrix."""
73
    a = np.dot(initial, rotation)
74
    cx, sx, rx = givens(a[2, 2], a[1, 2])
75
    cy, sy, ry = givens(rx, a[0, 2])
76
    cz, sz, rz = givens(cx * a[1, 1] - sx * a[2, 1],
77
                        cy * a[0, 1] - sy * (sx * a[1, 1] + cx * a[2, 1]))
78
    x = degrees(atan2(sx, cx))
79
    y = degrees(atan2(-sy, cy))
80
    z = degrees(atan2(sz, cz))
81
    return x, y, z
82

    
83

    
84
def hsv2rgb(h, s, v):
85
    """http://en.wikipedia.org/wiki/HSL_and_HSV
86

87
    h (hue) in [0, 360[
88
    s (saturation) in [0, 1]
89
    v (value) in [0, 1]
90

91
    return rgb in range [0, 1]
92
    """
93
    if v == 0:
94
        return 0, 0, 0
95
    if s == 0:
96
        return v, v, v
97

    
98
    i, f = divmod(h / 60., 1)
99
    p = v * (1 - s)
100
    q = v * (1 - s * f)
101
    t = v * (1 - s * (1 - f))
102

    
103
    if i == 0:
104
        return v, t, p
105
    elif i == 1:
106
        return q, v, p
107
    elif i == 2:
108
        return p, v, t
109
    elif i == 3:
110
        return p, q, v
111
    elif i == 4:
112
        return t, p, v
113
    elif i == 5:
114
        return v, p, q
115
    else:
116
        raise RuntimeError, 'h must be in [0, 360]'
117

    
118

    
119
def hsv(array, s=.9, v=.9):
120
    array = (array + array.min()) * 359. / (array.max() - array.min())
121
    result = np.empty((len(array.flat), 3))
122
    for rgb, h in zip(result, array.flat):
123
        rgb[:] = hsv2rgb(h, s, v)
124
    return np.reshape(result, array.shape + (3,))
125

    
126
## This code does the same, but requires pylab
127
## def cmap(array, name='hsv'):
128
##     import pylab
129
##     a = (array + array.min()) / array.ptp()
130
##     rgba = getattr(pylab.cm, name)(a)
131
##     return rgba[:-1] # return rgb only (not alpha)