def array_count_critical(rawdata,upsample=3,cut=True,cutoff=0.4): ''' Count critical points in the phase gradient map ''' # can only handle dim 3 for now assert len(shape(rawdata))==3 if cut: data = dct_upsample(dct_cut_antialias(rawdata,cutoff,ELECTRODE_SPACING),factor=upsample) else: data = dct_upsample(data,factor=upsample) dz = array_phase_gradient(data).transpose((2,0,1)) # extract curl via a kernal # take real component, centres have curl +- pi curl = np.complex64([[-1-1j,-1+1j],[1-1j,1+1j]]) curl = np.convolve2d(curl,np.ones((2,2))/4,'full') winding = arr([np.convolve2d(z,curl,'same','symm').real for z in dz]) # extract inflection points ( extrema, saddles ) # by looking for sign changes in derivatives # avoid points that are close to singular ok = ~(np.abs(winding)<1e-1)[...,:-1,:-1] ddx = np.diff(np.sign(dz.real),1,1)[...,:,:-1]/2 ddy = np.diff(np.sign(dz.imag),1,2)[...,:-1,:]/2 saddles = (ddx*ddy==-1)*ok maxima = (ddx*ddy== 1)*(ddx==-1)*ok minima = (ddx*ddy== 1)*(ddx== 1)*ok sum2 = lambda x: np.sum(np.int32(x),axis=(1,2)) nclockwise = sum2(winding>3) nwidersyns = sum2(winding<-3) nsaddles = sum2(saddles ) nmaxima = sum2(maxima ) nminima = sum2(minima ) return nclockwise, nwidersyns, nsaddles, nmaxima, nminima
def array_count_centers(data, upsample=3, cut=True, cutoff=0.4, electrode_spacing=0.4): ''' Counting centers -- looks for channels around which phase skips +-np.pi Parameters ---------- data : np.array Data should be sent in a 3-dimensional np.array of complex analytic signals, where the first two dimensions are the (x,y) spatial dimensions of the multi-electrode array. Other Parameters ---------------- upsample : int, default is 3 Upsampling factor for interpolating between electrodes cut : bool, default is True Whether to apply a spatial frequency cutoff. cutoff : float, default is 0.4 Spatial scale cutoff for analysis, in mm electrode_spacing : float, default 0.4 Spacing between electrodes in array in mm. Default is 0.4mm for the Utah arrays Returns ------- nclockwise : np.array number of clockwise centers found at each time point nanticlockwise : np.array number of anticlockwise centers found at each time point ''' if not len(shape(data)) == 3: raise ValueError('Data should be formatted with shape (x,y,t)') if cut: data = dct_upsample(dct_cut_antialias(data, cutoff, electrode_spacing), factor=upsample) else: data = dct_upsample(data, factor=upsample) dz = array_phase_gradient(data) curl = np.complex64([[-1 - 1j, -1 + 1j], [1 - 1j, 1 + 1j]]) curl = np.convolve2d(curl, np.ones((2, 2)) / 4, 'full') winding = arr([ real(np.convolve2d(z, curl, 'valid', 'symm')) for z in dz.transpose((2, 0, 1)) ]) nclockwise = np.sum(np.int32(winding > 3), axis=(1, 2)) nanticlockwise = np.sum(np.int32(winding < -3), axis=(1, 2)) return nclockwise, nanticlockwise
def array_count_centers(rawdata,upsample=3,cut=True,cutoff=0.4): ''' Counting centers -- looks for channels around which phase skips +-pi will miss rotating centers closer than half the electrode spacing ''' # can only handle dim 3 for now assert len(rawdata.shape)==3 if cut: data = dct_upsample(dct_cut_antialias( rawdata,cutoff,ELECTRODE_SPACING),factor=upsample) else: data = dct_upsample(data,factor=upsample) dz = array_phase_gradient(data) curl = np.complex64([[-1-1j,-1+1j],[1-1j,1+1j]]) curl = np.convolve2d(curl,np.ones((2,2))/4,'full') winding = arr([real(np.convolve2d(z,curl,'valid','symm')) for z in dz.transpose((2,0,1))]) nclockwise = np.sum(np.int32(winding> 3),axis=(1,2)) nwidersyns = np.sum(np.int32(winding<-3),axis=(1,2)) return nclockwise, nwidersyns
def array_count_critical(data, upsample=3, cut=True, cutoff=0.4, electrode_spacing=0.4): ''' Count critical points in the phase gradient map Parameters ---------- data : np.array Data should be sent in a 3-dimensional np.array of complex analytic signals, where the first two dimensions are the (x,y) spatial dimensions of the multi-electrode array. Other Parameters ---------------- upsample : int, default is 3 Upsampling factor for interpolating between electrodes cut : bool, default is True Whether to apply a spatial frequency cutoff. cutoff : float, default is 0.4 Spatial scale cutoff for analysis. electrode_spacing : float, default 0.4 Spacing between electrodes in array in mm. Default is 0.4mm for the Utah arrays Returns ------- nclockwise : np.array number of clockwise centers found at each time point nanticlockwise : np.array number of anticlockwise centers found at each time point nsaddles : np.array number of saddle points nmaxima : np.array number of local maxima nminima : np.array number of local minima ''' if not len(shape(data)) == 3: raise ValueError('Data should be formatted with shape (x,y,t)') if cut: data = dct_upsample(dct_cut_antialias(data, cutoff, electrode_spacing), factor=upsample) else: data = dct_upsample(data, factor=upsample) dz = array_phase_gradient(data).transpose((2, 0, 1)) # extract curl via a kernal # take real component, centres have curl +- np.pi curl = np.complex64([[-1 - 1j, -1 + 1j], [1 - 1j, 1 + 1j]]) curl = np.convolve2d(curl, np.ones((2, 2)) / 4, 'full') winding = arr([np.convolve2d(z, curl, 'same', 'symm').real for z in dz]) # extract inflection points ( extrema, saddles ) # by looking for sign changes in derivatives # avoid points that are close to singular ok = ~(np.abs(winding) < 1e-1)[..., :-1, :-1] ddx = np.diff(np.sign(dz.real), 1, 1)[..., :, :-1] / 2 ddy = np.diff(np.sign(dz.imag), 1, 2)[..., :-1, :] / 2 saddles = (ddx * ddy == -1) * ok maxima = (ddx * ddy == 1) * (ddx == -1) * ok minima = (ddx * ddy == 1) * (ddx == 1) * ok sum2 = lambda x: np.sum(np.int32(x), axis=(1, 2)) nclockwise = sum2(winding > 3) nanticlockwise = sum2(winding < -3) nsaddles = sum2(saddles) nmaxima = sum2(maxima) nminima = sum2(minima) return nclockwise, nanticlockwise, nsaddles, nmaxima, nminima