Skip to content

Commit 647f593

Browse files
committed
Update rate map to enable nan interpolation when smoothing is zero, and option to threshold small occupancy values.
1 parent d544450 commit 647f593

File tree

1 file changed

+59
-7
lines changed

1 file changed

+59
-7
lines changed

spatial_maps/maps.py

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ def _spike_map(x, y, t, spike_times, xbins, ybins):
5555
return values
5656

5757

58+
def interpolate_nan_2D(array, method='nearest'):
59+
from scipy import interpolate
60+
x = np.arange(0, array.shape[1])
61+
y = np.arange(0, array.shape[0])
62+
#mask invalid values
63+
array = np.ma.masked_invalid(array)
64+
xx, yy = np.meshgrid(x, y)
65+
#get only the valid values
66+
x1 = xx[~array.mask]
67+
y1 = yy[~array.mask]
68+
newarr = array[~array.mask]
69+
70+
return interpolate.griddata(
71+
(x1, y1), newarr.ravel(), (xx, yy),
72+
method=method, fill_value=0)
73+
74+
5875
class SpatialMap:
5976
def __init__(self, x, y, t, spike_times, box_size, bin_size, bin_count=None):
6077
box_size, bin_size = _adjust_bin_size(box_size, bin_size, bin_count)
@@ -79,25 +96,60 @@ def spike_map(self, smoothing, mask_zero_occupancy=False, **kwargs):
7996

8097
return spmap
8198

82-
def occupancy_map(self, smoothing, mask_zero_occupancy=False, **kwargs):
83-
if smoothing == 0.0:
84-
ocmap = copy(self.time_pos)
85-
else:
86-
ocmap = smooth_map(self.time_pos, self.bin_size, smoothing, **kwargs)
99+
def occupancy_map(self, smoothing, mask_zero_occupancy=False, threshold=None, **kwargs):
100+
'''Compute occupancy map as a histogram of postition
101+
weighted with time spent.
102+
Parameters:
103+
-----------
104+
mask_zero_occupancy : bool
105+
Set zero occupancy to nan
106+
threshold : float
107+
Set low occupancy times to zero as not to get spurious
108+
large values in rate.
109+
110+
'''
111+
ocmap = copy(self.time_pos)
112+
if threshold is not None:
113+
scmap[self.time_pos <= threshold] = 0
114+
if smoothing > 0:
115+
ocmap = smooth_map(ocmap, self.bin_size, smoothing, **kwargs)
87116

88117
if mask_zero_occupancy:
89118
ocmap[self.time_pos == 0] = np.nan
90119

91120
return ocmap
92121

93-
def rate_map(self, smoothing, mask_zero_occupancy=False, **kwargs):
122+
def rate_map(self, smoothing, mask_zero_occupancy=False, interpolate_invalid=False, threshold=None, **kwargs):
123+
'''Calculate rate map as spike_map / occupancy_map
124+
Parameters
125+
----------
126+
smoothing : float
127+
Smoothing of spike_map and occupancy_map before division
128+
mask_zero_occupancy : bool
129+
Set pixels of zero occupancy to nan
130+
interpolate_invalid : bool
131+
Interpolate rate_map after division to remove invalid values,
132+
if False, and mask_zero_occupancy is False,
133+
invalid values are set to zero.
134+
threshold : float
135+
Low occupancy can produce spurious high rate, a threshold sets
136+
occupancy below this to zero.
137+
kwargs : key word arguments to scipy.interpolate, when smoothing > 0
138+
Returns
139+
-------
140+
rate_map : array
141+
'''
94142
spike_map = self.spike_map(smoothing=smoothing, **kwargs)
95-
occupancy_map = self.occupancy_map(smoothing=smoothing, **kwargs)
143+
occupancy_map = self.occupancy_map(
144+
smoothing=smoothing, threshold=threshold, **kwargs)
96145
if mask_zero_occupancy:
97146
# to avoid infinity (x/0) we set zero occupancy to nan
98147
# this can be handy when analyzing low occupancy maps
99148
rate_map = spike_map / occupancy_map
100149
rate_map[self.time_pos == 0] = np.nan
150+
elif interpolate_invalid:
151+
rate_map = spike_map / occupancy_map
152+
rate_map = interpolate_nan_2D(rate_map)
101153
else:
102154
rate_map = spike_map / occupancy_map
103155
rate_map[np.isinf(rate_map)] = 0

0 commit comments

Comments
 (0)