Source code for slayerSNN.spikeFileIO

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from matplotlib import cm

[docs]class event(): ''' This class provides a way to store, read, write and visualize spike event. Members: * ``x`` (numpy ``int`` array): `x` index of spike event. * ``y`` (numpy ``int`` array): `y` index of spike event (not used if the spatial dimension is 1). * ``p`` (numpy ``int`` array): `polarity` or `channel` index of spike event. * ``t`` (numpy ``double`` array): `timestamp` of spike event. Time is assumend to be in ms. Usage: >>> TD = spikeFileIO.event(xEvent, yEvent, pEvent, tEvent) ''' def __init__(self, xEvent, yEvent, pEvent, tEvent): if yEvent is None: self.dim = 1 else: self.dim = 2 self.x = xEvent if type(xEvent) is np.ndarray else np.asarray(xEvent) # x spatial dimension self.y = yEvent if type(yEvent) is np.ndarray else np.asarray(yEvent) # y spatial dimension self.p = pEvent if type(pEvent) is np.ndarray else np.asarray(pEvent) # spike polarity self.t = tEvent if type(tEvent) is np.ndarray else np.asarray(tEvent) # time stamp in ms if not issubclass(self.x.dtype.type, np.integer): self.x = self.x.astype('int') if not issubclass(self.p.dtype.type, np.integer): self.p = self.p.astype('int') if self.dim == 2: if not issubclass(self.y.dtype.type, np.integer): self.y = self.y.astype('int') self.p -= self.p.min()
[docs] def toSpikeArray(self, samplingTime=1, dim=None): # Sampling time in ms ''' Returns a numpy tensor that contains the spike events sampled in bins of `samplingTime`. The array is of dimension (channels, height, time) or``CHT`` for 1D data. The array is of dimension (channels, height, width, time) or``CHWT`` for 2D data. Arguments: * ``samplingTime``: the width of time bin to use. * ``dim``: the dimension of the desired tensor. Assignes dimension itself if not provided. Usage: >>> spike = TD.toSpikeArray() ''' if self.dim == 1: if dim is None: dim = ( np.round(max(self.p)+1).astype(int), np.round(max(self.x)+1).astype(int), np.round(max(self.t)/samplingTime+1).astype(int) ) frame = np.zeros((dim[0], 1, dim[1], dim[2])) elif self.dim == 2: if dim is None: dim = ( np.round(max(self.p)+1).astype(int), np.round(max(self.y)+1).astype(int), np.round(max(self.x)+1).astype(int), np.round(max(self.t)/samplingTime+1).astype(int) ) frame = np.zeros((dim[0], dim[1], dim[2], dim[3])) return self.toSpikeTensor(frame, samplingTime).reshape(dim)
[docs] def toSpikeTensor(self, emptyTensor, samplingTime=1, randomShift=False, binningMode='OR'): # Sampling time in ms ''' Returns a numpy tensor that contains the spike events sampled in bins of `samplingTime`. The tensor is of dimension (channels, height, width, time) or``CHWT``. Arguments: * ``emptyTensor`` (``numpy or torch tensor``): an empty tensor to hold spike data * ``samplingTime``: the width of time bin to use. * ``randomShift``: flag to shift the sample in time or not. Default: False. * ``binningMode``: the way spikes are binned. 'SUM' or 'OR' are supported. Default: 'OR' Usage: >>> spike = TD.toSpikeTensor( torch.zeros((2, 240, 180, 5000)) ) ''' if randomShift is True: tSt = np.random.randint( max( int(self.t.min() / samplingTime), int(self.t.max() / samplingTime) - emptyTensor.shape[3], emptyTensor.shape[3] - int(self.t.max() / samplingTime), 1, ) ) else: tSt = 0 xEvent = np.round(self.x).astype(int) pEvent = np.round(self.p).astype(int) tEvent = np.round(self.t/samplingTime).astype(int) - tSt # print('shifted sequence by', tSt) if self.dim == 1: validInd = np.argwhere((xEvent < emptyTensor.shape[2]) & (pEvent < emptyTensor.shape[0]) & (tEvent < emptyTensor.shape[3]) & (xEvent >= 0) & (pEvent >= 0) & (tEvent >= 0)) if binningMode.upper() == 'OR': emptyTensor[pEvent[validInd], 0, xEvent[validInd], tEvent[validInd]] = 1/samplingTime elif binningMode.upper() == 'SUM': emptyTensor[pEvent[validInd], 0, xEvent[validInd], tEvent[validInd]] += 1/samplingTime else: raise Exception('Unsupported binningMode. It was {}'.format(binningMode)) elif self.dim == 2: yEvent = np.round(self.y).astype(int) validInd = np.argwhere((xEvent < emptyTensor.shape[2]) & (yEvent < emptyTensor.shape[1]) & (pEvent < emptyTensor.shape[0]) & (tEvent < emptyTensor.shape[3]) & (xEvent >= 0) & (yEvent >= 0) & (pEvent >= 0) & (tEvent >= 0)) if binningMode.upper() == 'OR': emptyTensor[pEvent[validInd], yEvent[validInd], xEvent[validInd], tEvent[validInd]] = 1/samplingTime elif binningMode.upper() == 'SUM': emptyTensor[pEvent[validInd], yEvent[validInd], xEvent[validInd], tEvent[validInd]] += 1/samplingTime else: raise Exception('Unsupported binningMode. It was {}'.format(binningMode)) return emptyTensor
[docs]def spikeArrayToEvent(spikeMat, samplingTime=1): ''' Returns TD event from a numpy array (of dimension 3 or 4). The numpy array must be of dimension (channels, height, time) or``CHT`` for 1D data. The numpy array must be of dimension (channels, height, width, time) or``CHWT`` for 2D data. Arguments: * ``spikeMat``: numpy array with spike information. * ``samplingTime``: time width of each time bin. Usage: >>> TD = spikeFileIO.spikeArrayToEvent(spike) ''' if spikeMat.ndim == 3: spikeEvent = np.argwhere(spikeMat > 0) xEvent = spikeEvent[:,1] yEvent = None pEvent = spikeEvent[:,0] tEvent = spikeEvent[:,2] elif spikeMat.ndim == 4: spikeEvent = np.argwhere(spikeMat > 0) xEvent = spikeEvent[:,2] yEvent = spikeEvent[:,1] pEvent = spikeEvent[:,0] tEvent = spikeEvent[:,3] else: raise Exception('Expected numpy array of 3 or 4 dimension. It was {}'.format(spikeMat.ndim)) return event(xEvent, yEvent, pEvent, tEvent * samplingTime)
[docs]def read1Dspikes(filename): ''' Reads one dimensional binary spike file and returns a TD event. The binary file is encoded as follows: * Each spike event is represented by a 40 bit number. * First 16 bits (bits 39-24) represent the neuronID. * Bit 23 represents the sign of spike event: 0=>OFF event, 1=>ON event. * the last 23 bits (bits 22-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. Usage: >>> TD = spikeFileIO.read1Dspikes(file_path) ''' with open(filename, 'rb') as inputFile: inputByteArray = inputFile.read() inputAsInt = np.asarray([x for x in inputByteArray]) xEvent = (inputAsInt[0::5] << 8) | inputAsInt[1::5] pEvent = inputAsInt[2::5] >> 7 tEvent =( (inputAsInt[2::5] << 16) | (inputAsInt[3::5] << 8) | (inputAsInt[4::5]) ) & 0x7FFFFF return event(xEvent, None, pEvent, tEvent/1000) # convert spike times to ms
[docs]def encode1Dspikes(filename, TD): ''' Writes one dimensional binary spike file from a TD event. The binary file is encoded as follows: * Each spike event is represented by a 40 bit number. * First 16 bits (bits 39-24) represent the neuronID. * Bit 23 represents the sign of spike event: 0=>OFF event, 1=>ON event. * the last 23 bits (bits 22-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. * ``TD`` (an ``spikeFileIO.event``): TD event. Usage: >>> spikeFileIO.write1Dspikes(file_path, TD) ''' if TD.dim != 1: raise Exception('Expected Td dimension to be 1. It was: {}'.format(TD.dim)) xEvent = np.round(TD.x).astype(int) pEvent = np.round(TD.p).astype(int) tEvent = np.round(TD.t * 1000).astype(int) # encode spike time in us outputByteArray = bytearray(len(tEvent) * 5) outputByteArray[0::5] = np.uint8( (xEvent >> 8) & 0xFF00 ).tobytes() outputByteArray[1::5] = np.uint8( (xEvent & 0xFF) ).tobytes() outputByteArray[2::5] = np.uint8(((tEvent >> 16) & 0x7F) | (pEvent.astype(int) << 7) ).tobytes() outputByteArray[3::5] = np.uint8( (tEvent >> 8 ) & 0xFF ).tobytes() outputByteArray[4::5] = np.uint8( tEvent & 0xFF ).tobytes() with open(filename, 'wb') as outputFile: outputFile.write(outputByteArray)
[docs]def read2Dspikes(filename): ''' Reads two dimensional binary spike file and returns a TD event. It is the same format used in neuromorphic datasets NMNIST & NCALTECH101. The binary file is encoded as follows: * Each spike event is represented by a 40 bit number. * First 8 bits (bits 39-32) represent the xID of the neuron. * Next 8 bits (bits 31-24) represent the yID of the neuron. * Bit 23 represents the sign of spike event: 0=>OFF event, 1=>ON event. * The last 23 bits (bits 22-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. Usage: >>> TD = spikeFileIO.read2Dspikes(file_path) ''' with open(filename, 'rb') as inputFile: inputByteArray = inputFile.read() inputAsInt = np.asarray([x for x in inputByteArray]) xEvent = inputAsInt[0::5] yEvent = inputAsInt[1::5] pEvent = inputAsInt[2::5] >> 7 tEvent =( (inputAsInt[2::5] << 16) | (inputAsInt[3::5] << 8) | (inputAsInt[4::5]) ) & 0x7FFFFF return event(xEvent, yEvent, pEvent, tEvent/1000) # convert spike times to ms
[docs]def encode2Dspikes(filename, TD): ''' Writes two dimensional binary spike file from a TD event. It is the same format used in neuromorphic datasets NMNIST & NCALTECH101. The binary file is encoded as follows: * Each spike event is represented by a 40 bit number. * First 8 bits (bits 39-32) represent the xID of the neuron. * Next 8 bits (bits 31-24) represent the yID of the neuron. * Bit 23 represents the sign of spike event: 0=>OFF event, 1=>ON event. * The last 23 bits (bits 22-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. * ``TD`` (an ``spikeFileIO.event``): TD event. Usage: >>> spikeFileIO.write2Dspikes(file_path, TD) ''' if TD.dim != 2: raise Exception('Expected Td dimension to be 2. It was: {}'.format(TD.dim)) xEvent = np.round(TD.x).astype(int) yEvent = np.round(TD.y).astype(int) pEvent = np.round(TD.p).astype(int) tEvent = np.round(TD.t * 1000).astype(int) # encode spike time in us outputByteArray = bytearray(len(tEvent) * 5) outputByteArray[0::5] = np.uint8(xEvent).tobytes() outputByteArray[1::5] = np.uint8(yEvent).tobytes() outputByteArray[2::5] = np.uint8(((tEvent >> 16) & 0x7F) | (pEvent.astype(int) << 7) ).tobytes() outputByteArray[3::5] = np.uint8( (tEvent >> 8 ) & 0xFF ).tobytes() outputByteArray[4::5] = np.uint8( tEvent & 0xFF ).tobytes() with open(filename, 'wb') as outputFile: outputFile.write(outputByteArray)
[docs]def read3Dspikes(filename): ''' Reads binary spike file for spike event in height, width and channel dimension and returns a TD event. The binary file is encoded as follows: * Each spike event is represented by a 56 bit number. * First 12 bits (bits 56-44) represent the xID of the neuron. * Next 12 bits (bits 43-32) represent the yID of the neuron. * Next 8 bits (bits 31-24) represents the channel ID of the neuron. * The last 24 bits (bits 23-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. Usage: >>> TD = spikeFileIO.read3Dspikes(file_path) ''' with open(filename, 'rb') as inputFile: inputByteArray = inputFile.read() inputAsInt = np.asarray([x for x in inputByteArray]) xEvent = (inputAsInt[0::7] << 4 ) | (inputAsInt[1::7] >> 4 ) yEvent = (inputAsInt[2::7] ) | ( (inputAsInt[1::7] & 0x0F) << 8 ) pEvent = inputAsInt[3::7] tEvent =( (inputAsInt[4::7] << 16) | (inputAsInt[5::7] << 8) | (inputAsInt[6::7]) ) return event(xEvent, yEvent, pEvent, tEvent/1000) # convert spike times to ms
[docs]def encode3Dspikes(filename, TD): ''' Writes binary spike file for TD event in height, width and channel dimension. The binary file is encoded as follows: * Each spike event is represented by a 56 bit number. * First 12 bits (bits 56-44) represent the xID of the neuron. * Next 12 bits (bits 43-32) represent the yID of the neuron. * Next 8 bits (bits 31-24) represents the channel ID of the neuron. * The last 24 bits (bits 23-0) represent the spike event timestamp in microseconds. Arguments: * ``filename`` (``string``): path to the binary file. * ``TD`` (an ``spikeFileIO.event``): TD event. Usage: >>> spikeFileIO.write3Dspikes(file_path, TD) ''' if TD.dim != 2: raise Exception('Expected Td dimension to be 2. It was: {}'.format(TD.dim)) xEvent = np.round(TD.x).astype(int) yEvent = np.round(TD.y).astype(int) pEvent = np.round(TD.p).astype(int) tEvent = np.round(TD.t * 1000).astype(int) # encode spike time in us outputByteArray = bytearray(len(tEvent) * 7) outputByteArray[0::7] = np.uint8(xEvent >> 4).tobytes() outputByteArray[1::7] = np.uint8( ((xEvent << 4) & 0xFF) | (yEvent >> 8) & 0xFF00 ).tobytes() outputByteArray[2::7] = np.uint8( yEvent & 0xFF ).tobytes() outputByteArray[3::7] = np.uint8( pEvent ).tobytes() outputByteArray[4::7] = np.uint8( (tEvent >> 16 ) & 0xFF ).tobytes() outputByteArray[5::7] = np.uint8( (tEvent >> 8 ) & 0xFF ).tobytes() outputByteArray[6::7] = np.uint8( tEvent & 0xFF ).tobytes() with open(filename, 'wb') as outputFile: outputFile.write(outputByteArray)
[docs]def read1DnumSpikes(filename): ''' Reads a tuple specifying neuron, start of spike region, end of spike region and number of spikes from binary spike file. The binary file is encoded as follows: * Number of spikes data is represented by an 80 bit number. * First 16 bits (bits 79-64) represent the neuronID. * Next 24 bits (bits 63-40) represents the start time in microseconds. * Next 24 bits (bits 39-16) represents the end time in microseconds. * Last 16 bits (bits 15-0) represents the number of spikes. Arguments: * ``filename`` (``string``): path to the binary file Usage: >>> nID, tSt, tEn, nSp = spikeFileIO.read1DnumSpikes(file_path) ``tSt`` and ``tEn`` are returned in milliseconds ''' with open(filename, 'rb') as inputFile: inputByteArray = inputFile.read() inputAsInt = np.asarray([x for x in inputByteArray]) neuronID = (inputAsInt[0::10] << 8) | inputAsInt[1::10] tStart = (inputAsInt[2::10] << 16) | (inputAsInt[3::10] << 8) | (inputAsInt[4::10]) tEnd = (inputAsInt[5::10] << 16) | (inputAsInt[6::10] << 8) | (inputAsInt[7::10]) nSpikes = (inputAsInt[8::10] << 8) | inputAsInt[9::10] return neuronID, tStart/1000, tEnd/1000, nSpikes # convert spike times to ms
[docs]def encode1DnumSpikes(filename, nID, tSt, tEn, nSp): ''' Writes binary spike file given a tuple specifying neuron, start of spike region, end of spike region and number of spikes. The binary file is encoded as follows: * Number of spikes data is represented by an 80 bit number * First 16 bits (bits 79-64) represent the neuronID * Next 24 bits (bits 63-40) represents the start time in microseconds * Next 24 bits (bits 39-16) represents the end time in microseconds * Last 16 bits (bits 15-0) represents the number of spikes Arguments: * ``filename`` (``string``): path to the binary file * ``nID`` (``numpy array``): neuron ID * ``tSt`` (``numpy array``): region start time (in milliseconds) * ``tEn`` (``numpy array``): region end time (in milliseconds) * ``nSp`` (``numpy array``): number of spikes in the region Usage: >>> spikeFileIO.encode1DnumSpikes(file_path, nID, tSt, tEn, nSp) ''' neuronID = np.round(nID).astype(int) tStart = np.round(tSt * 1000).astype(int) # encode spike time in us tEnd = np.round(tEn * 1000).astype(int) # encode spike time in us nSpikes = np.round(nSp).astype(int) outputByteArray = bytearray(len(neuronID) * 10) outputByteArray[0::10] = np.uint8( neuronID >> 8 ).tobytes() outputByteArray[1::10] = np.uint8( neuronID ).tobytes() outputByteArray[2::10] = np.uint8( tStart >> 16 ).tobytes() outputByteArray[3::10] = np.uint8( tStart >> 8 ).tobytes() outputByteArray[4::10] = np.uint8( tStart ).tobytes() outputByteArray[5::10] = np.uint8( tEnd >> 16 ).tobytes() outputByteArray[6::10] = np.uint8( tEnd >> 8 ).tobytes() outputByteArray[7::10] = np.uint8( tEnd ).tobytes() outputByteArray[8::10] = np.uint8( nSpikes >> 8 ).tobytes() outputByteArray[9::10] = np.uint8( nSpikes ).tobytes() with open(filename, 'wb') as outputFile: outputFile.write(outputByteArray)
[docs]def readNpSpikes(filename, fmt='xypt', timeUnit=1e-3): ''' Reads numpy spike event and returns a TD event. The numpy array is assumed to be of nEvent x event diension. Arguments: * ``filename`` (``string``): path to the file. * ``fmt`` (``string``): format of event. For e.g.'xypt' means the event data is arrange in x data, y data, p data and time data. * ``timeUnit`` (``double``): factor to scale the time data to convert it into seconds. Default: 1e-3 (ms). Usage: >>> TD = spikeFileIO.readNpSpikes(file_path) >>> TD = spikeFileIO.readNpSpikes(file_path, fmt='xypt') >>> TD = spikeFileIO.readNpSpikes(file_path, timeUnit=1e-6) ''' npEvent = np.load(filename) if fmt=='xypt': if npEvent.shape[1] == 3: return event(npEvent[:, 0].astype('int'), None, npEvent[:, 1], npEvent[:, 2] * timeUnit * 1e3) elif npEvent.shape[1] == 4: return event(npEvent[:, 0], npEvent[:, 1], npEvent[:, 2], npEvent[:, 3] * timeUnit * 1e3) else: raise Exception('Numpy array format did not match. Ecpected it to be nEvents x eventDim.') else: raise Exception("fmt='%s' not implemented."%(fmt))
[docs]def encodeNpSpikes(filename, TD, fmt='xypt', timeUnit=1e-3): ''' Writes TD event into numpy file. Arguments: * ``filename`` (``string``): path to the binary file. * ``TD`` (an ``spikeFileIO.event``): TD event. Usage: >>> spikeFileIO.write1Dspikes(file_path, TD) >>> spikeFileIO.write1Dspikes(file_path, TD, fmt='xypt') ''' if fmt=='xypt': if TD.dim ==1: npEvent = np.zeros((len(TD.x), 3)) npEvent[:, 0] = TD.x npEvent[:, 1] = TD.p npEvent[:, 2] = TD.t elif TD.dim==2: npEvent = np.zeros((len(TD.x), 4)) npEvent[:, 0] = TD.x npEvent[:, 1] = TD.y npEvent[:, 2] = TD.p npEvent[:, 3] = TD.t else: raise Exception('Numpy array format did not match. Ecpected it to be nEvents x eventDim.') else: raise Exception("fmt='%s' not implemented."%(fmt)) np.save(filename, npEvent)
def _showTD1D(TD, fig=None, frameRate=24, preComputeFrames=True, repeat=False, plot=True): if TD.dim !=1: raise Exception('Expected Td dimension to be 1. It was: {}'.format(TD.dim)) if fig is None: fig = plt.figure() interval = 1e3 / frameRate # in ms xDim = TD.x.max()+1 tMax = TD.t.max() tMin = TD.t.min() pMax = TD.p.max()+1 minFrame = int(np.floor(tMin / interval)) maxFrame = int(np.ceil(tMax / interval )) + 1 # ignore preComputeFrames raster, = plt.plot([], [], '.') scanLine, = plt.plot([], []) plt.axis((tMin -0.1*tMax, 1.1*tMax, -0.1*xDim, 1.1*xDim)) def animate(i): tEnd = (i + minFrame + 1) * interval ind = (TD.t < tEnd) # update raster raster.set_data(TD.t[ind], TD.x[ind]) # update raster scan line scanLine.set_data([tEnd + interval, tEnd + interval], [0, xDim]) anim = animation.FuncAnimation(fig, animate, frames=maxFrame, interval=interval, repeat=repeat) if plot is True: plt.show() return anim def _showTD2D(TD, fig=None, frameRate=24, preComputeFrames=True, repeat=False, plot=True): if TD.dim != 2: raise Exception('Expected Td dimension to be 2. It was: {}'.format(TD.dim)) if fig is None: fig = plt.figure() interval = 1e3 / frameRate # in ms xDim = TD.x.max()+1 yDim = TD.y.max()+1 if preComputeFrames is True: minFrame = int(np.floor(TD.t.min() / interval)) maxFrame = int(np.ceil(TD.t.max() / interval )) image = plt.imshow(np.zeros((yDim, xDim, 3))) frames = np.zeros( (maxFrame-minFrame, yDim, xDim, 3)) # precompute frames for i in range(len(frames)): tStart = (i + minFrame) * interval tEnd = (i + minFrame + 1) * interval timeMask = (TD.t >= tStart) & (TD.t < tEnd) rInd = (timeMask & (TD.p == 1)) gInd = (timeMask & (TD.p == 2)) bInd = (timeMask & (TD.p == 0)) frames[i, TD.y[rInd], TD.x[rInd], 0] = 1 frames[i, TD.y[gInd], TD.x[gInd], 1] = 1 frames[i, TD.y[bInd], TD.x[bInd], 2] = 1 def animate(frame): image.set_data(frame) return image anim = animation.FuncAnimation(fig, animate, frames=frames, interval=interval, repeat=repeat) else: minFrame = int(np.floor(TD.t.min() / interval)) maxFrame = int(np.ceil(TD.t.max() / interval )) image = plt.imshow(np.zeros((yDim, xDim, 3))) def animate(i): tStart = (i + minFrame) * interval tEnd = (i + minFrame + 1) * interval frame = np.zeros((yDim, xDim, 3)) timeMask = (TD.t >= tStart) & (TD.t < tEnd) rInd = (timeMask & (TD.p == 1)) gInd = (timeMask & (TD.p == 2)) bInd = (timeMask & (TD.p == 0)) frame[TD.y[rInd], TD.x[rInd], 0] = 1 frame[TD.y[gInd], TD.x[gInd], 1] = 1 frame[TD.y[bInd], TD.x[bInd], 2] = 1 image.set_data(frame) return image anim = animation.FuncAnimation(fig, animate, frames=maxFrame-minFrame, interval=interval, repeat=repeat) # # save the animation as an mp4. This requires ffmpeg or mencoder to be # # installed. The extra_args ensure that the x264 codec is used, so that # # the video can be embedded in html5. You may need to adjust this for # # your system: for more information, see # # http://matplotlib.sourceforge.net/api/animation_api.html # if saveAnimation: anim.save('showTD_animation.mp4', fps=30) if plot is True: plt.show() return anim
[docs]def showTD(TD, fig=None, frameRate=24, preComputeFrames=True, repeat=False): ''' Visualizes TD event. Arguments: * ``TD``: spike event to visualize. * ``fig``: figure to plot animation. Default is ``None``, in which case a figure is created. * ``frameRate``: framerate of visualization. * ``preComputeFrames``: flag to enable precomputation of frames for faster visualization. Default is ``True``. * ``repeat``: flag to enable repeat of animation. Default is ``False``. Usage: >>> showTD(TD) ''' if fig is None: fig = plt.figure() if TD.dim == 1: _showTD1D(TD, fig, frameRate=frameRate, preComputeFrames=preComputeFrames, repeat=repeat) else: _showTD2D(TD, fig, frameRate=frameRate, preComputeFrames=preComputeFrames, repeat=repeat)
[docs]def animTD(TD, fig=None, frameRate=24, preComputeFrames=True, repeat=True): ''' Reutrn animation object for TD event. Arguments: * ``TD``: spike event to visualize. * ``fig``: figure to plot animation. Default is ``None``, in which case a figure is created. * ``frameRate``: framerate of visualization. * ``preComputeFrames``: flag to enable precomputation of frames for faster visualization. Default is ``True``. * ``repeat``: flag to enable repeat of animation. Default is ``True``. Usage: >>> anim = animTD(TD) ''' if fig is None: fig = plt.figure() if TD.dim == 1: anim = _showTD1D(TD, fig, frameRate=frameRate, preComputeFrames=preComputeFrames, repeat=repeat, plot=False) else: anim = _showTD2D(TD, fig, frameRate=frameRate, preComputeFrames=preComputeFrames, repeat=repeat, plot=False) plt.close(anim._fig) return anim
# def spikeMat2TD(spikeMat, samplingTime=1): # Sampling time in ms # addressEvent = np.argwhere(spikeMat > 0) # # print(addressEvent.shape) # return event(addressEvent[:,2], addressEvent[:,1], addressEvent[:,0], addressEvent[:,3] * samplingTime)