Functions for Basic e-phys

Author: Konstantinos Nasiotis

The previous tutorials explained how to perform the spike sorting and the conversion to LFPs.

LFPs can be analyzed using the extensive library of methods from EEG and MEG research already present in Brainstorm. These signal processing libraries include artifact removal, time-frequency, connectivity, statistics and several other tools that are essential for analyzing electrophysiological data.

Spiking activity can be analyzed in a set of functions that is present in the Electrophysiology library, and help researchers understand their selectivity and interaction with the LFPs.

The figures in this page have been created with the spiking events that are initially available in the raw file. If you run one of the spike-sorters within Brainstorm you might get different events, leading to different visualizations.

functionsIntro.png

Import LFP epochs

For the purpose of the tutorial, the timings around the presentation of the Superflow are selected as the segment of interest of the recordings. To import those segments: right-click on the LFP Link to raw file > Import in database.

importDatabase.gif

importedTrials.gif

Note: As stated earlier on this tutorial, in order for the spiking functions to work, the spiking events should be named with the convention: “Spikes Channel ChannelLabel”. If the spike sorting is performed within Brainstorm, this should be done automatically. Users that import their own spiking events should organize their events in a compatible to Brainstorm format.

Tuning curves

The tuning curve is the most basic method of getting insights about neuronal selectivity in electrophysiology. Different conditions of a stimulus presentation are expected to elicit different number of spikes. Those conditions that each neuron is more “tuned” to, are expected to be recognized from a plot that shows that neuron’s number of spikes for each condition.

The tuning curves can be derived straight from the link to the raw file, since the events are already available in that file after the spike-sorting step. For computing the tuning curves, either the initial link to raw file or the link to the LFP file can be used.

For using the tuning curve function, users have to make these selections:

For the purpose of this tutorial, users should (considering the WaveClus spike sorting results):

This will create two figures with the spatial selectivity of these two neurons on the selected conditions. The figures show the firing rate of the neurons on each condition, along with the 95% confidence intervals.

tuningCurves_2022.png

Noise correlation

Correlation is a measure of the degree to which trial-to-trial fluctuations in response strength are shared by a pair of neurons. This is typically quantified as the Pearson correlation of the spike count responses to repeated presentations of identical stimuli under the same behavioral conditions (Cohen & Kohn 2011).

noiseCorrelation_new.png

References

Spike field coherence

The spike-field coherence will effectively show the relationship between the spiking activity of a neuron, with the ongoing LFP oscillations as a matter of frequency. So, if a neuron is phase-locked to a specific frequency of the LFP oscillations, the SFC will show an increase only for that frequency. The computation of the SFC is based on the method from Fries et al. (2001). For more information users can check the supplementary figure 3 on the link listed at the end of this section.

SFCprocess.gif

Once the computation is complete, double clicking on the created SFC icon will open the computed SFC for a single neuron. Each neuron can be selected from the drop-down box in the Display tab. The figure that appears, effectively shows the influence that the selected neuron has on all the electrodes on the recording, in all frequencies (up to the Nyquist limit).

SFCOutput_new.png

On the image above, the SFC from neuron 1 on channel with label “AD03” is shown for all 32 channels, for all frequencies up to 250 Hz (the trials were downsampled at 500 Hz, so we can get frequencies about to the Nyquist frequency). A clear cutoff frequency is shown above 150 Hz, since the LFP signals during the conversion were bandpass filtered at [0.5 - 150] Hz.

This neuron shows increased SFC on the Beta band and some high-gamma on the electrode that is picked up, and also some on the neighouring electrodes.

The increased low frequency SFC is ambigous due to the window selected around the spikes [-150,150] ms, and could be affected by edge-effects.

References

Raster plot / Peristimulus time histogram

The raster plot/PSTH are basic methods for visualizing the selectivity of individual neurons. All trials are concatenated to display each neuron's behavior on all trials of a condition. These processes provide information on the selectivity but also the latency of the neurons on the experimental condition selected.

Raster plot per neuron

This function visualizes each neuron's spiking activity as a single dot for all trials selected. Users can select each individual neuron from the drop-down box in the Display tab. This function, does not use any binning (the x-axis is comprised with the same length as the time-samples of the trials).

The first neuron that was picked up on the electrode with label AD01 (Spikes Channel AD01 |1|) shows spiking latency ~120-180 ms after the stimulus presentation.

RPNeuronWindow.gif

PSTH per neuron

This function computes the firing rate for all trials of a given condition, for each neuron. The bin size is a user-defined time-period and the spike-counts are computed and normalized for the bin-duration for each neuron.

This creates a matrix [Ntrials x Nbins] of the firing rates (where n is the number of trials and b the number of bins that fit the trial time-window). Users can select each individual neuron from the drop-down box in the Display tab.

For the purpose of the tutorial, select a Bin size of 50ms.

The following figure shows the firing rate of some neurons increasing as a response to the stimulus presented (around 150-200 ms). Additionally, the bin at -75ms relative to the stimulus onset, there is a consistent increase on all neurons, indicative of the presence of an artifact within that bin.

PSTH_per_Neuron.png

For visualizing the 95% confidense intervals (1000 samples permutation test) of the firing rate of each bin, for each neuron, select the Butterfly visualization by right clicking on the display, and sequentially: Display options -> Display Mode -> Butterfly

PSTH per channel

(Binned firing rate per trial on the implanted topography)

We also included a second method that allows visualization of the binned spiking activity on the topography of the electrodes.

As with the previous PSTH plot method (PSTH per neuron), users have to define a bin-size where the spiking activity of each neuron will be computed. Since a single channel might record spiking activity from multiple neurons, this visualization will present only the firing activity for the first neuron. Therefore, for each condition, a separate file will be created for the first (or only) neuron that was picked up from that channel, containing the binned firing rates.

Users need to import the trials and sequentially Run > Electrophysiology > PSTH per Channel.

For the tutorial purposes, users should drag and drop the trials that correspond to condition Stim On: 1 to the process box and sequentially Run > Electrophysiology > PSTH per Channel.

This will create 96 binned trial files after the completion of the computations.

By right clicking on each of them and sequentially: SEEG -> 3D electrodes Head/Cortex/MRI 3D

users can visualize the firing rate activity on the implanted device and navigate through the binned trials. The smaller the bin size selected, the closer to real-time spiking activity one can get on the topography.

This visualization can be very helpful for monitoring propagating spiking activity across the implants.

PSTH_per_Channel.png

Spike triggered average

The spike triggered average (STA) is a method for measuring the relation between the neuronal spiking and the local field potentials. If a neuron influences a distant electrode, the waveform of the STA should reveal these correlations. Effectively, this can be visualized with the averaging of the LFPs of all electrodes around the timing of a single neuron’s spiking and normalized by the spike-count.

STAWindow.gif

This process creates as many new files as individual neurons picked up from all electrodes (electrodes that picked up more than one neuron will create one file per neuron). The example below shows 70 new files created after the computation of the STA.

STAOutput_butterfly_2022.png

To display the STA on the implant geometry, users have to select one of the STA files, right click > SEEG > 2D Layout. Ctrl+E allows the display of the electrode labels. This menu is available only if the positions of the electrodes have been imported previously.

The following figure displays the STA for the neuron that was located on electrode AD01. It is clear that the LFPs close to the electrode that picked up the neuron are affected by this neuron’s firing. For easy navigation to the next neuron’s STA, press F3.

STAOutput_2022.png

Spiking phase locking values

A hypothesis for how brain regions exchange information is through "communication by coherence" (Fries, 2005). The ongoing oscillations are hypothesized that create windows of opportunity for information exchange. Therefore, the relative timing of spiking activity to LFP oscillations of distant neuronal populations can encode stimulus information.

On this example, the oscillations in the alpha band for channel AD06 are selected for checking the spiking phase selectivity of all neurons from all channels.

phase_locking_window.gif

The function works in a multiplicative way: Phase locking values will be computed for all present neurons in the selected trials, for all selected sensors. e.g. for n Neurons and k channels, the dropdown will consist of n*k labels.

The following figure shows the phase selectivity of a neuron on channel AD06, relative to the ongoing alpha oscillations on the same channel.

phase_locking_results.png

The total number of spikes for the selected neuron, the Rayleigh circular significance test, and the neuron's preferred phase are also displayed.

Reference

Scripting

The following script from the Brainstorm distribution reproduces the analysis presented in this tutorial page: brainstorm3/toolbox/script/tutorial_ephys.m

1 function tutorial_ephys(tutorial_dir) 2 % TUTORIAL_EPHYS: Script that reproduces the online tutorials "Brainstorm's Suite for Multi-unit Electrophysiology" 3 % 4 % REFERENCE: 5 % - https://neuroimage.usc.edu/brainstorm/e-phys/Introduction 6 % - https://neuroimage.usc.edu/brainstorm/e-phys/SpikeSorting 7 % - https://neuroimage.usc.edu/brainstorm/e-phys/RawToLFP 8 % - https://neuroimage.usc.edu/brainstorm/e-phys/functions 9 % 10 % INPUTS: 11 % tutorial_dir: Directory where the sample_ephys.zip file has been unzipped 12 13 % @============================================================================= 14 % This function is part of the Brainstorm software: 15 % https://neuroimage.usc.edu/brainstorm 16 % 17 % Copyright (c) University of Southern California & McGill University 18 % This software is distributed under the terms of the GNU General Public License 19 % as published by the Free Software Foundation. Further details on the GPLv3 20 % license can be found at http://www.gnu.org/copyleft/gpl.html. 21 % 22 % FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE 23 % UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY 24 % WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF 25 % MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY 26 % LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. 27 % 28 % For more information type "brainstorm license" at command prompt. 29 % =============================================================================@ 30 % 31 % Author: Francois Tadel, 2022 32 33 34 %% ===== FILES TO IMPORT ===== 35 % You have to specify the folder in which the tutorial dataset is unzipped 36 if (nargin == 0) || isempty(tutorial_dir) || ~file_exist(tutorial_dir) 37 error('The first argument must be the full path to the tutorial dataset folder.'); 38 end 39 % Build the path of the files to import 40 T1Nii = fullfile(tutorial_dir, 'sample_ephys', 'floyd_t1.nii'); 41 CortexMesh = fullfile(tutorial_dir, 'sample_ephys', 'floyd_cortex.mesh'); 42 PlxFile = fullfile(tutorial_dir, 'sample_ephys', 'ytu288c-01.plx'); 43 PosFile = fullfile(tutorial_dir, 'sample_ephys', 'ytu288c-01_electrodes.txt'); 44 EvtFile = fullfile(tutorial_dir, 'sample_ephys', 'ytu288c-01_events.csv'); 45 % Check if the folder contains the required files 46 if ~file_exist(T1Nii) || ~file_exist(PlxFile) 47 error(['The folder ' tutorial_dir ' does not contain the folder from the file sample_ephys.zip.']); 48 end 49 % Subject name 50 SubjectName = 'Floyd'; 51 52 53 %% ===== CREATE PROTOCOL ===== 54 % Start brainstorm without the GUI 55 if ~brainstorm('status') 56 brainstorm nogui 57 end 58 % Protocol name 59 ProtocolName = 'Tutorial_e-Phys'; 60 % Delete existing protocol 61 gui_brainstorm('DeleteProtocol', ProtocolName); 62 % Create new protocol 63 gui_brainstorm('CreateProtocol', ProtocolName, 0, 0); 64 % Start a new report 65 bst_report('Start'); 66 67 68 %% ===== IMPORT ANATOMY ===== 69 % Process: Import MRI 70 bst_process('CallProcess', 'process_import_mri', [], [], ... 71 'subjectname', SubjectName, ... 72 'mrifile', {T1Nii, 'ALL'}); 73 % Process: MNI normalization 74 bst_process('CallProcess', 'process_mni_normalize', [], [], ... 75 'subjectname', SubjectName, ... 76 'method', 'maff8'); 77 % Process: Generate head surface 78 bst_process('CallProcess', 'process_generate_head', [], [], ... 79 'subjectname', SubjectName, ... 80 'nvertices', 10000, ... 81 'erodefactor', 0, ... 82 'fillfactor', 2); 83 % Import cortex surface 84 iSubject = 1; 85 [iSurf, CortexFile] = import_surfaces(iSubject, CortexMesh, 'MESH', 0); 86 87 88 %% ===== ACCESS THE RECORDINGS ===== 89 % Process: Create link to raw file 90 sFilesRaw = bst_process('CallProcess', 'process_import_data_raw', [], [], ... 91 'subjectname', SubjectName, ... 92 'datafile', {PlxFile, 'EEG-PLEXON'}); 93 % Process: Import from file 94 bst_process('CallProcess', 'process_evt_import', sFilesRaw, [], ... 95 'evtfile', {EvtFile, 'CSV-TIME'}, ... 96 'delete', 0); 97 % Process: Add EEG positions 98 bst_process('CallProcess', 'process_channel_addloc', sFilesRaw, [], ... 99 'channelfile', {PosFile, 'ASCII_NXYZ_WORLD'}, ... 100 'fixunits', 0, ... 101 'vox2ras', 1); 102 % Process: Set channels type 103 bst_process('CallProcess', 'process_channel_settype', sFilesRaw, [], ... 104 'sensortypes', '', ... 105 'newtype', 'SEEG'); 106 107 % Display anatomy and sensors 108 hFig = view_channels_3d(sFilesRaw.ChannelFile, 'SEEG', 'scalp', 1); 109 hFig = view_surface(CortexFile{1}, 0.8, [1 0 0], hFig); 110 figure_3d('SetStandardView', hFig, 'right'); 111 bst_report('Snapshot', hFig, [], 'Anatomy'); 112 % Unload everything 113 bst_memory('UnloadAll', 'Forced'); 114 115 116 %% ===== SPIKE SORTING ===== 117 % Not executed here, in order to keep the original spiking events from the PLX file 118 119 % % Process: WaveClus 120 % sFilesWavclus = bst_process('CallProcess', 'process_spikesorting_waveclus', sFilesRaw, [], ... 121 % 'spikesorter', 'waveclus', ... 122 % 'binsize', 8, ... 123 % 'parallel', 0, ... 124 % 'usessp', 1, ... 125 % 'make_plots', 0, ... 126 % 'edit', 0); 127 128 % % Process: UltraMegaSort2000 129 % sFilesUMS = bst_process('CallProcess', 'process_spikesorting_ultramegasort2000', sFilesRaw, [], ... 130 % 'spikesorter', 'ultramegasort2000', ... 131 % 'binsize', 40, ... 132 % 'parallel', 0, ... 133 % 'usessp', 1, ... 134 % 'highpass', 700, ... 135 % 'lowpass', 4800, ... 136 % 'edit', 4800); 137 138 % % Process: KiloSort 139 % sFilesKilo = bst_process('CallProcess', 'process_spikesorting_kilosort', sFilesRaw, [], ... 140 % 'spikesorter', 'kilosort', ... 141 % 'binsize', 40, ... 142 % 'GPU', 0, ... 143 % 'usessp', 1, ... 144 % 'edit', 1); 145 146 147 %% ===== CONVERT TO LFP ===== 148 % Process: Convert Raw to LFP 149 sFilesLfp = bst_process('CallProcess', 'process_convert_raw_to_lfp', sFilesRaw, [], ... 150 'binsize', 40, ... 151 'usessp', 1, ... 152 'LFP_fs', 1000, ... 153 'freqlist', [], ... 154 'filterbounds', [0.5, 150], ... 155 'despikeLFP', 0, ... 156 'parallel', 0); 157 % Process: Import MEG/EEG: Events 158 sFilesLfpEpochs = bst_process('CallProcess', 'process_import_data_event', sFilesLfp, [], ... 159 'subjectname', SubjectName, ... 160 'condition', '', ... 161 'eventname', 'Stim On 1, Stim On 2, Stim On 3, Stim On 4, Stim On 5, Stim On 6, Stim On 7, Stim On 8, Stim On 9', ... 162 'timewindow', [], ... 163 'epochtime', [-0.5, 1], ... 164 'split', 0, ... 165 'createcond', 0, ... 166 'ignoreshort', 1, ... 167 'usectfcomp', 1, ... 168 'usessp', 1, ... 169 'freq', 500, ... 170 'baseline', 'all', ... 171 'blsensortypes', 'SEEG'); 172 173 174 %% ===== TUNING CURVES ===== 175 % Process: Tuning curves 176 bst_process('CallProcess', 'process_tuning_curves', sFilesLfp, [], ... 177 'eventsel', {'Stim On 1', 'Stim On 2', 'Stim On 3', 'Stim On 4', 'Stim On 5', 'Stim On 6', 'Stim On 7', 'Stim On 8', 'Stim On 9'}, ... 178 'spikesel', {'Spikes Channel AD06', 'Spikes Channel AD08 |1|'}, ... 179 'timewindow', [0.05, 0.12]); 180 close(findobj('Type','figure')); 181 182 183 %% ===== NOISE CORRELATION ===== 184 % Process: Noise correlation 185 sFilesNoiseCorr = bst_process('CallProcess', 'process_noise_correlation', sFilesLfpEpochs, [], ... 186 'timewindow', [0, 0.3]); 187 % Process: Snapshot: Time-frequency maps 188 bst_process('CallProcess', 'process_snapshot', sFilesNoiseCorr, [], ... 189 'type', 'timefreq', ... % Time-frequency maps 190 'modality', 6, ... % SEEG 191 'Comment', 'Noise correlation'); 192 193 194 %% ===== SPIKE FIELD COHERENCE ===== 195 % Process: Select data files in: Floyd/*/Stim On 1 196 sFilesStim1 = bst_process('CallProcess', 'process_select_files_data', [], [], ... 197 'subjectname', SubjectName, ... 198 'condition', '', ... 199 'tag', 'Stim On 1', ... 200 'includebad', 0, ... 201 'includeintra', 0, ... 202 'includecommon', 0); 203 % Process: Spike field coherence 204 sFilesSFC = bst_process('CallProcess', 'process_spike_field_coherence', sFilesStim1, [], ... 205 'timewindow', [-0.15, 0.15], ... 206 'sensortypes', 'EEG, SEEG', ... 207 'parallel', 0); 208 % Process: Snapshot: Time-frequency maps 209 hFig = view_timefreq(sFilesSFC.FileName, 'SingleSensor', 'Spikes Channel AD03'); 210 bst_report('Snapshot', hFig, [], 'Spike field coherence'); 211 close(hFig); 212 213 214 %% ===== RASTER PLOT ===== 215 % Process: Raster plot per neuron 216 sFilesRaster = bst_process('CallProcess', 'process_rasterplot_per_neuron', sFilesStim1, []); 217 % Process: Snapshot: Time-frequency maps 218 hFig = view_timefreq(sFilesRaster.FileName, 'SingleSensor', 'Spikes Channel AD01 |1|'); 219 panel_time('SetCurrentTime', 0.158); 220 bst_report('Snapshot', hFig, [], 'Raster plot per neuron'); 221 close(hFig); 222 223 224 %% ===== SPIKE TRIGGERED AVERAGE ===== 225 % Process: Spike triggered average 226 sFilesAvg = bst_process('CallProcess', 'process_spike_triggered_average', sFilesStim1, [], ... 227 'timewindow', [-0.15, 0.15], ... 228 'parallel', 0); 229 230 % Process: Select data files in: Floyd/*/Stim On 1 (AD01 #1) 231 sFilesAvgAD01 = bst_process('CallProcess', 'process_select_files_data', [], [], ... 232 'subjectname', SubjectName, ... 233 'condition', '', ... 234 'tag', 'Stim On 1 (AD01 #1)', ... 235 'includebad', 0, ... 236 'includeintra', 0, ... 237 'includecommon', 0); 238 % Process: Snapshot: Recordings time series 239 bst_process('CallProcess', 'process_snapshot', sFilesAvgAD01, [], ... 240 'type', 'data', ... % Recordings time series 241 'modality', 6, ... % SEEG 242 'Comment', 'Spike triggered average: AD01 #1'); 243 % View 2DLayout 244 hFig = view_topography(sFilesAvgAD01.FileName, 'SEEG', '2DLayout'); 245 bst_report('Snapshot', hFig, [], 'Spike triggered average: AD01 #1'); 246 close(hFig); 247 248 % Save and display report 249 ReportFile = bst_report('Save', []); 250 bst_report('Open', ReportFile); 251 252 253








Feedback: Comments, bug reports, suggestions, questions
Email address (if you expect an answer):


e-phys/functions (last edited 2022-05-03 12:15:00 by FrancoisTadel)