@@ -17,12 +17,15 @@ def _adjust_bin_size(box_size, bin_size=None, bin_count=None):
1717 box_size = np .array ([box_size , box_size ])
1818
1919 if bin_size is None :
20- bin_size = np .array ([box_size [0 ] / bin_count [0 ],
21- box_size [1 ] / bin_count [1 ]])
20+ bin_size = np .array ([box_size [0 ] / bin_count [0 ], box_size [1 ] / bin_count [1 ]])
2221
2322 # round bin size of to closest requested bin size
24- bin_size = np .array ([box_size [0 ] / int (box_size [0 ] / bin_size [0 ]),
25- box_size [1 ] / int (box_size [1 ] / bin_size [1 ])])
23+ bin_size = np .array (
24+ [
25+ box_size [0 ] / int (box_size [0 ] / bin_size [0 ]),
26+ box_size [1 ] / int (box_size [1 ] / bin_size [1 ]),
27+ ]
28+ )
2629
2730 return box_size , bin_size
2831
@@ -42,115 +45,113 @@ def smooth_map(rate_map, bin_size, smoothing, **kwargs):
4245def _occupancy_map (x , y , t , xbins , ybins ):
4346 t_ = np .append (t , t [- 1 ] + np .median (np .diff (t )))
4447 time_in_bin = np .diff (t_ )
45- values , _ , _ = np .histogram2d (
46- x , y , bins = [xbins , ybins ], weights = time_in_bin )
48+ values , _ , _ = np .histogram2d (x , y , bins = [xbins , ybins ], weights = time_in_bin )
4749 return values
4850
4951
5052def _spike_map (x , y , t , spike_times , xbins , ybins ):
5153 t_ = np .append (t , t [- 1 ] + np .median (np .diff (t )))
5254 spikes_in_bin , _ = np .histogram (spike_times , t_ )
53- values , _ , _ = np .histogram2d (
54- x , y , bins = [xbins , ybins ], weights = spikes_in_bin )
55+ values , _ , _ = np .histogram2d (x , y , bins = [xbins , ybins ], weights = spikes_in_bin )
5556 return values
5657
5758
58- def interpolate_nan_2D (array , method = ' nearest' ):
59+ def interpolate_nan_2D (array , method = " nearest" ):
5960 from scipy import interpolate
61+
6062 x = np .arange (0 , array .shape [1 ])
6163 y = np .arange (0 , array .shape [0 ])
62- #mask invalid values
64+ # mask invalid values
6365 array = np .ma .masked_invalid (array )
6466 xx , yy = np .meshgrid (x , y )
65- #get only the valid values
67+ # get only the valid values
6668 x1 = xx [~ array .mask ]
6769 y1 = yy [~ array .mask ]
6870 newarr = array [~ array .mask ]
6971
7072 return interpolate .griddata (
71- (x1 , y1 ), newarr .ravel (), (xx , yy ),
72- method = method , fill_value = 0 )
73+ (x1 , y1 ), newarr .ravel (), (xx , yy ), method = method , fill_value = 0
74+ )
7375
7476
7577class SpatialMap :
76- def __init__ (self , x , y , t , spike_times , box_size , bin_size , bin_count = None ):
78+ def __init__ (
79+ self , smoothing = 0.05 , box_size = [1.0 , 1.0 ], bin_size = 0.02 , bin_count = None
80+ ):
81+ """
82+ Parameters
83+ ----------
84+ smoothing : float
85+ Smoothing of spike_map and occupancy_map before division
86+ box_size : Sequence-like
87+ Size of box in x and y direction
88+ bin_size : float
89+ Resolution of spatial maps
90+ """
7791 box_size , bin_size = _adjust_bin_size (box_size , bin_size , bin_count )
7892 xbins , ybins = _make_bins (box_size , bin_size )
79- self .spike_pos = _spike_map (x , y , t , spike_times , xbins , ybins )
80- self .time_pos = _occupancy_map (x , y , t , xbins , ybins )
81- assert all (self .spike_pos [self .time_pos == 0 ] == 0 )
8293
94+ self .smoothing = smoothing
8395 self .bin_size = bin_size
8496 self .box_size = box_size
8597 self .xbins = xbins
8698 self .ybins = ybins
8799
88- def spike_map (self , smoothing , mask_zero_occupancy = False , ** kwargs ):
89- if smoothing == 0.0 :
90- spmap = copy (self .spike_pos )
91- else :
92- spmap = smooth_map (self .spike_pos , self .bin_size , smoothing , ** kwargs )
93-
100+ def spike_map (self , x , y , t , spike_times , mask_zero_occupancy = True , ** kwargs ):
101+ spmap = _spike_map (x , y , t , spike_times , self .xbins , self .ybins )
102+ spmap = (
103+ smooth_map (spmap , self .bin_size , self .smoothing , ** kwargs )
104+ if self .smoothing
105+ else spmap
106+ )
94107 if mask_zero_occupancy :
95- spmap [self .time_pos == 0 ] = np .nan
96-
108+ spmap [_occupancy_map (x , y , t , self .xbins , self .ybins ) == 0 ] = np .nan
97109 return spmap
98110
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 )
116-
111+ def occupancy_map (self , x , y , t , mask_zero_occupancy = True , ** kwargs ):
112+ ocmap = _occupancy_map (x , y , t , self .xbins , self .ybins )
113+ ocmap_copy = copy (ocmap ) # to mask zero occupancy after smoothing
114+ ocmap = (
115+ smooth_map (ocmap , self .bin_size , self .smoothing , ** kwargs )
116+ if self .smoothing
117+ else ocmap
118+ )
117119 if mask_zero_occupancy :
118- ocmap [self .time_pos == 0 ] = np .nan
119-
120+ ocmap [ocmap_copy == 0 ] = np .nan
120121 return ocmap
121122
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
123+ def rate_map (
124+ self ,
125+ x ,
126+ y ,
127+ t ,
128+ spike_times ,
129+ mask_zero_occupancy = True ,
130+ interpolate_invalid = False ,
131+ ** kwargs
132+ ):
133+ """Calculate rate map as spike_map / occupancy_map
124134 Parameters
125135 ----------
126- smoothing : float
127- Smoothing of spike_map and occupancy_map before division
128136 mask_zero_occupancy : bool
129137 Set pixels of zero occupancy to nan
130138 interpolate_invalid : bool
131139 Interpolate rate_map after division to remove invalid values,
132140 if False, and mask_zero_occupancy is False,
133141 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.
137142 kwargs : key word arguments to scipy.interpolate, when smoothing > 0
138143 Returns
139144 -------
140145 rate_map : array
141- '''
142- spike_map = self .spike_map (smoothing = smoothing , ** kwargs )
143- occupancy_map = self . occupancy_map (
144- smoothing = smoothing , threshold = threshold , ** kwargs )
145- if mask_zero_occupancy :
146- # to avoid infinity (x/0) we set zero occupancy to nan
147- # this can be handy when analyzing low occupancy maps
148- rate_map = spike_map / occupancy_map
149- rate_map [self . time_pos == 0 ] = np . nan
146+ """
147+ spike_map = self .spike_map (
148+ x , y , t , spike_times , mask_zero_occupancy = mask_zero_occupancy , ** kwargs
149+ )
150+ # to avoid infinity (x/0) we set zero occupancy to nan
151+ occupancy_map = self . occupancy_map ( x , y , t , mask_zero_occupancy = True , ** kwargs )
152+ rate_map = spike_map / occupancy_map
153+ if not mask_zero_occupancy :
154+ rate_map [np . isnan ( rate_map ) ] = 0
150155 elif interpolate_invalid :
151- rate_map = spike_map / occupancy_map
152156 rate_map = interpolate_nan_2D (rate_map )
153- else :
154- rate_map = spike_map / occupancy_map
155- rate_map [np .isinf (rate_map )] = 0
156157 return rate_map
0 commit comments