Visualizing Spike times: The Raster plot

 

32channelRasterPlot
Fig 28: An example of a 32 channel raster plot. The raster plot visualizes the last n spike times. In this example, we see the last 10 spike responses on all 32 channels.

 

Raster plots are a very informative visualization technique of neural activity. They allow us to easily inspect the neural activity over time span on a single as well as on all channels in a very intuitive way. Furthermore, by taking certain stimulation parameters into account, they also allow us to visualize the spiking activity w.r.t. specific stimuli.

By now it should be no surprise that the Datapipeline API already provides a ready-to-use raster plot plugin. And as you may remember from the very beginning of this tutorial (cf: Fig4 and Fig5), the data stored by the Detector plugin is also stored in special buffers which allow us to store the data of the last N trials or sweeps.  And unsurprisingly, those buffers are also already available as plugins which we simply add to our existing pipeline. So now let's get a bit more ambitious and apply all the knowledge we have gained so far and add a single channel as well as multichannel raster plot at the same time.
And here is what we are going to do to make it all happen.
- We need to clone the data stream coming from the spike detector into two streams -- one for the single and one for the multichannel raster plot
- We need to add a buffer containing the data for the 32 channel plot and make it large enough to store the data of 10 sweeps.
- We need also need to add a buffer containing the data for a single channel and make it large enough to store the data of 100 sweeps.
- We need to add the single-channel and the 32 channel raster plot.
- We need to add the display to show the original data
- And we need to add two datasinks to get rid of the data at the end of the pipeline branch.
So let's go and do this!

This what the final code looks like:

def example18():
    sampleRate = 24414
    numChannels = 32
    sweepLen = int(sampleRate/2)
    enableCISimulation = True
    enableBlanking = True
    #set up the stimulation parameter object    
    #set stimulation parameters     
    level_dB=5  # in dB in relation to 100 uA
    clickRate=50  # 300, 900, 1800
    ears='left' # other options are  'right' and 'both' Must be set to 'left' or 'right' during simulation
    duration = 0.01 # This defines the duration of the  stimulation
    numClicks = 1
    nloop = 0
    reference_Simulation=0.100 # set reference to 100 uA
    levelRePeak = True  # normally we set levels relative to RMS If you want to set them relative to abs max instead, set this to True
    clickShape_CI_Simulation = np.array([0,1,0,-1,0]) # use a biphasic pulse
    blankingEndOffsetInSeconds = 0.02 # This offset shifts the end of the blanking. This can be useful if the filter artifacts occur beyond the actual duration of the stimulation.
    #set up the stimulation parameter object    
    stimulatorModule.soundPlayer=stimulatorModule.pygameSoundHardware()
    stimulatorModule.soundPlayer.sampleRate = 25000
    stim=stimulatorModule.clickTrainObject()
    stim.clickShape= clickShape_CI_Simulation
    stim.stimParams['duration (s)']=duration # this parameter controls the duration of the stimulation.
    stim.stimParams['ABL (dB)']=level_dB #ABL means Average Binaural Level
    stim.stimParams['clickRate (Hz)']=clickRate
    stim.stimParams['Nloop']=nloop
    stim.stimParams['numClicks']=numClicks
    stim.reference=reference_Simulation
    stim.clickShape=clickShape_CI_Simulation
    stim.levelRePeak=levelRePeak
    stim.ears=ears
    stim.ready()  

    aDatasource = pipeline.Datasource()  
    aDatasource.setName("Eyphs PushDataSource")
    sweepSpikeFiltFiltPlugin = pipeline.SweepSpikeFiltFiltPlugin()
    sweepSpikeFiltFiltPlugin.setName("Eyphs SweepSpikeFiltFiltPlugin")
    
    aSpikeSimulationPlugin = pipeline.SpikeSimulationPlugin()   
    aSpikeSimulationPlugin.setName("Eyphs SpikeSimulationPlugin")
    aSpikeSimulationPlugin.loadSpikeTemplates("FilteredSpikeTemplates.npy")
    debugSpikeAmplitudes = [0.0001, 0.0001, 0.0001, 0.0001]
    debugSpikePositions = [0.1, 0.2, 0.3, 0.4]
    aSpikeSimulationPlugin.setDebug(False)
    aSpikeSimulationPlugin.setDebugSpikeAmplitudes(debugSpikeAmplitudes)
    aSpikeSimulationPlugin.setDebugSpikePositions(debugSpikePositions)
    
    aSweepInterBlankingPlugin = pipeline.SweepInterBlankingPlugin()
    aSweepInterBlankingPlugin.setName("Eyphs SweepInterBlankingPlugin")
    aSweepInterBlankingPlugin.setEndOffsetInSeconds(blankingEndOffsetInSeconds)
    aSweepInterBlankingPlugin.setEnabled(enableBlanking)
    
    aArtifactSimulationPlugin = pipeline.ArtifactSimulationPlugin()
    aArtifactSimulationPlugin.setName("Eyphs ArtifactSimulationPlugin")
    aArtifactSimulationPlugin.setEnabled(enableCISimulation)
    aSpikeSimulationPlugin = pipeline.SpikeSimulationPlugin()
    
    aSpikeDetector = pipeline.SpikeDetector()
    aSpikeDetector.setName("Eyphs SpikeDetector")
    aSpikeDetector.setStimEndOffsetInSeconds(blankingEndOffsetInSeconds)
    
    aCloneDatasource = pipeline.CloneDatasource(2)
    aCloneDatasource.setName("aCloneDatasource")
    aDatasink0 = pipeline.Datasink()
    aDatasink0.setName("Eyphs DataSink0")
    aDatasink1 = pipeline.Datasink()
    aDatasink1.setName("Eyphs DataSink1")
    
    aNSweepsBufferPlugin = pipeline.NSweepsBufferPlugin()
    aNSweepsBufferPlugin.setName("Eyphs aNSweepsBufferPlugin")

    a100SweepBufferPlugin = pipeline.NSweepsBufferPlugin(numSweeps=100)
    a100SweepBufferPlugin.setName("Eyphs a100SweepsBufferPlugin")
    
    aNSweepsRasterPlotPlugin = pipeline.NSweepsRasterPlotPlugin()
    aNSweepsRasterPlotPlugin.setName("Ephys aNSweepsRasterPlotPlugin")
    
    aSingleChannelRasterPlotPlugin = pipeline.NSweepsRasterPlotPlugin(singleChannelPlot = True)
    aSingleChannelRasterPlotPlugin.setName("Ephys aSingleChannelRasterPlotPlugin")
    
    aDisplay = pipeline.MplSweepDataDisplay(plt)

    #assemble the pipeline
    aDatasource.setOutput(aArtifactSimulationPlugin)
    aArtifactSimulationPlugin.setOutput(sweepSpikeFiltFiltPlugin)
    sweepSpikeFiltFiltPlugin.setOutput(aSpikeSimulationPlugin)
    aSpikeSimulationPlugin.setOutput(aSweepInterBlankingPlugin)
    aSweepInterBlankingPlugin.setOutput(aSpikeDetector)
    aSpikeDetector.setOutput(aCloneDatasource)
    aCloneDatasource.setOutput(aNSweepsBufferPlugin,0)
    aCloneDatasource.setOutput(a100SweepBufferPlugin,1)
       
    aNSweepsBufferPlugin.setOutput(aNSweepsRasterPlotPlugin)
    aNSweepsRasterPlotPlugin.setOutput(aDisplay)
    aDisplay.setOutput(aDatasink0)
    
    a100SweepBufferPlugin.setOutput(aSingleChannelRasterPlotPlugin)
    aSingleChannelRasterPlotPlugin.setOutput(aDatasink1)
    
    for n in range(100):
        #generate multichannel data and random background noise
        sigTupel=tuple(0.000015*np.random.normal(0,1.0, numChannels*sweepLen))
        data=RZ2ephys.MCsweep(sigTupel,sweepLen,sampleRate,0)
        stimObjectCopy = copy.deepcopy(stim)
        aDataframe = pipeline.Dataframe()
        aDataframe.setStimObject(stimObjectCopy)
        aDataframe.setFrameNumber(n)
        aDataframe.setData(data)
        aDatasource.addDataframe(aDataframe)
        aDatasource.run()

And this what the output of the code looks like:

EphysSearchPipeline
Fig 29: The output of example18 is identical to the output of the EphysSearch.py program because the pipelines are virtually identical.

Conceptually, example18() has nothing new to offer. by now you have done it all several times. However, if you look very closely, you may notice that the pipeline has been assembled in a slightly different way compared to what we have done in example17(). And if you compare example18() with what you find in the code of the EphysSearch.py program, you will notice that we have just recreated the simulation pipeline used in that particular program! So congratulations on implementing your first data processing pipeline that can be used to analyze real electrophysiological data!
Tip: If you run this program, you can select the single-channel raster plot of a particular channel by clicking on a channel plot with your mouse.