-
Notifications
You must be signed in to change notification settings - Fork 0
/
extrafuncs.py
171 lines (154 loc) · 5.69 KB
/
extrafuncs.py
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''Extra functions that do not exist yet in Numpy
'''
import numpy as np
def index_to_bool(arrayOfIndexes):
'''Convert array of indexes into a 2D array,
where each column indicates if element'''
elements = np.unique(arrayOfIndexes)
arrayOfBool = np.zeros((arrayOfIndexes.shape[0],elements.shape[0]),dtype=bool)
for inde,elem in enumerate(elements):
arrayOfBool[:,inde] = arrayOfIndexes==elem
return(arrayOfBool,elements)
def bool_to_index(arrayOfBool):
pass
'''From http://projects.scipy.org/numpy/ticket/1036'''
def ismember_newer(totest, members):
"""
A setmember1d, which works for totest arrays with duplicate values
"""
uniques_in_test, rev_idx = np.unique1d(totest, return_inverse=True)
uniques_in_members_mask = np.setmember1d(uniques_in_test, members)
# Use this instead if members is not unique
# uniques_in_members_mask = setmember1d(uniques_in_test, unique1d(members))
return uniques_in_members_mask[rev_idx]
def ismember(a1,a2):
""" Test whether items from a2 are in a1.
This does the same thing as np.setmember1d, but works on
non-unique arrays.
Only a few (2-4) times slower than np.setmember1d, and a lot
faster than [i in a2 for i in a1].
An example that np.setmember1d gets wrong:
>>> a1 = np.array([5,4,5,3,4,4,3,4,3,5,2,1,5,5])
>>> a2 = [2,3,4]
>>> mask = ismember(a1,a2)
>>> a1[mask]
array([4, 3, 4, 4, 3, 4, 3, 2])
"""
a2 = set(a2)
a1 = np.asarray(a1)
ind = a1.argsort()
a1 = a1[ind]
mask = []
# need this bit because prev is not defined for first item
item = a1[0]
if item in a2:
mask.append(True)
a2.remove(item)
else:
mask.append(False)
prev = item
# main loop
for item in a1[1:]:
if item == prev:
mask.append(mask[-1])
elif item in a2:
mask.append(True)
prev = item
a2.remove(item)
else:
mask.append(False)
prev = item
# restore mask to original ordering of a1 and return
mask = np.array(mask)
return mask[ind.argsort()]
def moving_average_masked_OLD(marray,nsamples):
'''
Moving average that works with masked array.
The calculation is causal so the first elements of the result are the mean
over less samples than nsamples.
'''
result = np.ma.empty(marray.shape,dtype='float')
for indi in range(min(len(marray),nsamples)):
result[indi] = marray[:indi+1].mean()
for indi in range(nsamples,len(marray)):
result[indi] = marray[indi-nsamples+1:indi+1].mean()
return result
def moving_average_masked_OLD2(myarray,winsize):
'''
Moving average that works with masked arrays (of multiple rows).
marray is R x n
For each point, the average is taken over all elements in columns inside a moving window.
The calculation is causal so the first elements of the result are the mean
over less samples than nsamples.
'''
if len(myarray.shape)==1:
marray=myarray[np.newaxis,:]
else:
marray = myarray
(nRepeats, nSamples) = marray.shape
result = np.ma.empty(nSamples,dtype='float')
for indi in range(min(nSamples,winsize)):
result[indi] = marray[:,:indi+1].mean()
for indi in range(winsize,nSamples):
result[indi] = marray[:,indi-winsize+1:indi+1].mean()
return result
def moving_average_masked(myarray,winsize,sem=False):
'''
Moving average that works with masked arrays (of multiple rows).
marray is R x n
For each point, the average is taken over all elements in columns inside a moving window.
The calculation is causal so the first elements of the result are the mean
over less samples than nsamples.
'''
if len(myarray.shape)==1:
marray=np.ma.masked_array(myarray[np.newaxis,:])
else:
marray = np.ma.masked_array(myarray)
(nRepeats, nSamples) = marray.shape
valMean = np.ma.empty(nSamples,dtype='float')
valSEM = np.ma.empty(nSamples,dtype='float')
for indi in range(min(nSamples,winsize)):
thisChunk = marray[:,:indi+1]
valMean[indi] = thisChunk.mean()
if sem:
valSEM[indi] = thisChunk.std()/np.sqrt(thisChunk.count())
for indi in range(winsize,nSamples):
thisChunk = marray[:,indi-winsize+1:indi+1]
valMean[indi] = thisChunk.mean()
if sem:
valSEM[indi] = thisChunk.std()/np.sqrt(thisChunk.count())
if sem:
return (valMean,valSEM)
else:
return valMean
def moving_average_masked_acausal(myarray,winsize,sem=False):
'''
Moving average that works with masked arrays (of multiple rows).
marray is R x n
For each point, the average is taken over all elements in columns inside a moving window.
The calculation is acausal so the last elements of the result are the mean
over less samples than nsamples.
'''
if len(myarray.shape)==1:
marray=np.ma.masked_array(myarray[np.newaxis,:])
else:
marray = np.ma.masked_array(myarray)
(nRepeats, nSamples) = marray.shape
valMean = np.ma.empty(nSamples,dtype='float')
valSEM = np.ma.empty(nSamples,dtype='float')
for indi in range(nSamples-winsize):
thisChunk = marray[:,indi:indi+winsize]
valMean[indi] = thisChunk.mean()
if sem:
valSEM[indi] = thisChunk.std()/np.sqrt(thisChunk.count())
for indi in range(nSamples-winsize+1,nSamples):
thisChunk = marray[:,indi:nSamples]
valMean[indi] = thisChunk.mean()
if sem:
valSEM[indi] = thisChunk.std()/np.sqrt(thisChunk.count())
if sem:
return (valMean,valSEM)
else:
return valMean