File size: 4,202 Bytes
6250360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import numpy as np
import copy

TINY = np.exp(-100)
concat = np.concatenate
def is_2D(m):
    '''
    judge if a matrix is 2-D or not
    '''
    return len(np.shape(m)) == 2

def norm1(v):
    return np.sum(np.abs(v))

def norm2(v):
    return np.sqrt(np.sum(v ** 2))

def norm2_squared(v):
    return np.sum(v ** 2)


def cos_dist(v1, v2):
    length1 = norm2(v1)
    length2 = norm2(v2)
    return np.dot(v1, v2) / (length1 * length2)

def eu_dist(v1, v2):
    v = v1 - v2
    return norm2(v)

def chi_squared_dist(f1, f2):
    dist = 0
    for ff1, ff2 in zip(f1, f2):
        if ff1 + ff2 == 0:# color feature values are supposed to be non-negative. If this case happened, it means both ne and de are 0s 
            continue;
        dist += (ff1 - ff2) ** 2 * 1.0/ (ff1 + ff2) 
    return np.sqrt(dist)

def flatten(arr, ndim = 1):
    """
    flatten an multi-dimensional array to a certain degree.
    ndim: the number of dimensions after flatten
    """
    arr = np.asarray(arr)
    dims = len(arr.shape)
    shape = [np.prod(arr.shape[0: dims + 1 - ndim])]
    shape.extend(arr.shape[dims + 1 - ndim: dims])
    return np.reshape(arr, shape)

def arcsin(sins, xs = None):
    """
    cal arcsin.
    xs: if this parameter is provided, the returned arcsins will be within [0, 2*pi)
    otherwise the default [-pi/2, pi/2]
    """
    arcs = np.arcsin(sins);
    if xs != None:
        xs = np.asarray(xs)
        sins = np.asarray(sins)
        # if x > 0, then the corresponding mask value is  -1. The resulting angle unchanged: v = 0 - (-v) = v.  else, v = pi - v
        add_pi = xs < 0
        pi_mask = add_pi * np.pi
        # 0 --> 1, 1 --> -1
        arc_mask = 2 * add_pi - 1
        arcs = pi_mask - arcs * arc_mask

        # if x >= 0 and sin < 0, v = 2*pi + v
        add_2_pi = (xs >= 0) * (sins < 0)
        pi_mask = add_2_pi * 2 * np.pi
        arcs = pi_mask + arcs 
    return arcs
    
def sin(ys = None, lengths = None, xs = None, angles = None):
    """
    calculate sin with multiple kinds of parameters
    """
    if not angles is None:
        return np.sin(angles)
    
    if ys is None:
        raise ValueError('ys must be provided when "angles" is None ')

    if lengths is None:
        if xs is None:
            raise ValueError('xs must be provided when "lengths" is None ')
        lengths = np.sqrt(xs ** 2 + ys ** 2)
    
    if not np.iterable(lengths):
        sins = ys / lengths if lengths > 0 else 0
    else:
        lengths = np.asarray(lengths)
        shape = lengths.shape
        ys = flatten(ys)
        lengths = flatten(lengths)                
        sins = [y / length if length > 0 else 0 for (y, length) in zip(ys, lengths)]
        sins = np.reshape(sins, shape)
    return sins

def sum_all(m):
    """
    sum up all the elements in a multi-dimension array
    """
    return np.sum(m)
    
    
def clone(obj, deep = False):
    if not deep:
        return copy.copy(obj)
    return copy.deepcopy(obj)

def empty_list(length, etype):
    empty_list = [None] * length
    for i in xrange(length):
        if etype == list:
            empty_list[i] = []
        else:
            raise NotImplementedError
    
    return empty_list
            
def shuffle(arr):
    import random
    random.shuffle(arr)
        
def is_empty(a):
    '''
    tell whether an array is empty.
    If a is multidimensional, it is empty when it contains no entry in the last dimension.
    '''
    if a is None:
        return True
    
    shape = np.shape(a)
    if np.prod(shape) == 0:
        return True
    
    return False
    
def angle_with_x(x, y):
    """
    return the arctan x/y, in range [-pi, pi]
    """
    return np.arctan2(y, x)

def has_infty(x):
    test = x == np.infty
    return np.sum(test) > 0
    
def has_nan(x):
    x = np.asarray(x)
    test = x != x
    return np.sum(test) > 0

def has_nan_or_infty(x):
    if has_nan(x):
        return True
    
    if has_infty(x):
        return True
    
        
def iterable(x):
    return np.iterable(x)
    
def smooth(arr):
    result = [0] * len(arr)
    s = 0
    for idx, n in enumerate(arr):
        s += n
        result[idx] = s * 1.0 / (idx + 1)
    return result