def get_seq(data, bin_size, use_sqrt=True): """ Converts the data into a rec array using internally BinnedSpikeTrain. Parameters ---------- data : list of list of Spiketrain objects The outer list corresponds to trials and the inner list corresponds to the neurons recorded in that trial, such that data[l][n] is the Spiketrain of neuron n in trial l. Note that the number and order of Spiketrains objects per trial must be fixed such that data[l][n] and data[k][n] refer to the same spike generator for any choice of l,k and n. bin_size: quantity.Quantity Spike bin width use_sqrt: bool Boolean specifying whether or not to use square-root transform on spike counts (see original paper for motivation). Default is True Returns ------- seq data structure, whose nth entry (corresponding to the nth experimental trial) has fields * trialId: unique trial identifier * T: (1 x 1) number of timesteps * y: (yDim x T) neural data Raises ------ ValueError if `bin_size` is not a pq.Quantity. """ if not isinstance(bin_size, pq.Quantity): raise ValueError("'bin_size' must be of type pq.Quantity") seq = [] for dat in data: trial_id = dat[0] sts = dat[1] binned_sts = BinnedSpikeTrain(sts, binsize=bin_size) if use_sqrt: binned = np.sqrt(binned_sts.to_array()) else: binned = binned_sts.to_array() seq.append((trial_id, binned_sts.num_bins, binned)) seq = np.array(seq, dtype=[('trialId', np.int), ('T', np.int), ('y', 'O')]) # Remove trials that are shorter than one bin width if len(seq) > 0: trials_to_keep = seq['T'] > 0 seq = seq[trials_to_keep] return seq
def get_epochs(self, epoch, nbins=100, filter=True): """The function return a list of windows, with the brain activity associated to a specific task/epoch and its respective labels""" print(f'Selecting epoch {epoch} from correct segments...') tasks = [] targets = [] duration = [] for i, seg in enumerate(self.blk.segments): # Every run performed by the monkey is checked, and if it is not correct it is ignored if filter and seg.annotations['correct'] == 0: print(f'\tSegment {i} discarded') continue evt = seg.events[0] labels = [str(lab).strip().lower() for lab in evt.labels] limits = None # Given a run, we check if the epoch of interest is part of it and in case we get the limits for it if epoch.lower() in labels: idx = labels.index(epoch.lower()) limits = (evt[idx], evt[idx + 1], epoch) else: print(f'\t Segment {i}, epoch not present in this segment') spk = seg.spiketrains if limits is not None: # For every found task we return a window sparse_array = BinnedSpikeTrain(spk, n_bins=nbins, t_start=limits[0], t_stop=limits[1]) tasks.append(sparse_array.to_array().astype('float32')) targets.append(seg.annotations['obj']) duration.append(limits[1] - limits[0]) return np.array(tasks), targets, duration
def spike_field_coherence(signal, spiketrain, **kwargs): """ Calculates the spike-field coherence between a analog signal(s) and a (binned) spike train. The current implementation makes use of scipy.signal.coherence(). Additional kwargs will will be directly forwarded to scipy.signal.coherence(), except for the axis parameter and the sampling frequency, which will be extracted from the input signals. The spike_field_coherence function receives an analog signal array and either a binned spike train or a spike train containing the original spike times. In case of original spike times the spike train is binned according to the sampling rate of the analog signal array. The AnalogSignal object can contain one or multiple signal traces. In case of multiple signal traces, the spike field coherence is calculated individually for each signal trace and the spike train. Parameters ---------- signal : neo AnalogSignalArray object 'signal' contains n analog signals. spiketrain : SpikeTrain or BinnedSpikeTrain Single spike train to perform the analysis on. The binsize of the binned spike train must match the sampling_rate of signal. KWArgs ------ All KWArgs are passed to scipy.signal.coherence(). Returns ------- coherence : complex Quantity array contains the coherence values calculated for each analog signal trace in combination with the spike train. The first dimension corresponds to the frequency, the second to the number of the signal trace. frequencies : Quantity array contains the frequency values corresponding to the first dimension of the 'coherence' array Example ------- Plot the SFC between a regular spike train at 20 Hz, and two sinusoidal time series at 20 Hz and 23 Hz, respectively. >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from quantities import ms, mV, Hz, kHz >>> import neo, elephant >>> t = pq.Quantity(range(10000),units='ms') >>> f1, f2 = 20. * Hz, 23. * Hz >>> signal = neo.AnalogSignal(np.array([ np.sin(f1 * 2. * np.pi * t.rescale(s)), np.sin(f2 * 2. * np.pi * t.rescale(s))]).T, units=pq.mV, sampling_rate=1. * kHz) >>> spiketrain = neo.SpikeTrain( range(t[0], t[-1], 50), units='ms', t_start=t[0], t_stop=t[-1]) >>> sfc, freqs = elephant.sta.spike_field_coherence( signal, spiketrain, window='boxcar') >>> plt.plot(freqs, sfc[:,0]) >>> plt.plot(freqs, sfc[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('SFC') >>> plt.xlim((0, 60)) >>> plt.show() """ if not hasattr(scipy.signal, 'coherence'): raise AttributeError('scipy.signal.coherence is not available. The sfc ' 'function uses scipy.signal.coherence for ' 'the coherence calculation. This function is ' 'available for scipy version 0.16 or newer. ' 'Please update you scipy version.') # spiketrains type check if not isinstance(spiketrain, (SpikeTrain, BinnedSpikeTrain)): raise TypeError( "spiketrain must be of type SpikeTrain or BinnedSpikeTrain, " "not %s." % type(spiketrain)) # checks on analogsignal if not isinstance(signal, AnalogSignalArray): raise TypeError( "Signal must be an AnalogSignalArray, not %s." % type(signal)) if len(signal.shape) > 1: # num_signals: number of individual traces in the analog signal num_signals = signal.shape[1] elif len(signal.shape) == 1: num_signals = 1 else: raise ValueError("Empty analog signal.") len_signals = signal.shape[0] # bin spiketrain if necessary if isinstance(spiketrain, SpikeTrain): spiketrain = BinnedSpikeTrain( spiketrain, binsize=signal.sampling_period) # check the start and stop times of signal and spike trains if spiketrain.t_start < signal.t_start: raise ValueError( "The spiketrain starts earlier than the analog signal.") if spiketrain.t_stop > signal.t_stop: raise ValueError( "The spiketrain stops later than the analog signal.") # check equal time resolution for both signals if spiketrain.binsize != signal.sampling_period: raise ValueError( "The spiketrain and signal must have a " "common sampling frequency / binsize") # calculate how many bins to add on the left of the binned spike train delta_t = spiketrain.t_start - signal.t_start if delta_t % spiketrain.binsize == 0: left_edge = int((delta_t / spiketrain.binsize).magnitude) else: raise ValueError("Incompatible binning of spike train and LFP") right_edge = int(left_edge + spiketrain.num_bins) # duplicate spike trains spiketrain_array = np.zeros((1, len_signals)) spiketrain_array[0, left_edge:right_edge] = spiketrain.to_array() spiketrains_array = np.squeeze( np.repeat(spiketrain_array, repeats=num_signals, axis=0)).transpose() # calculate coherence frequencies, sfc = scipy.signal.coherence( spiketrains_array, signal.magnitude, fs=signal.sampling_rate.rescale('Hz').magnitude, axis=0, **kwargs) return (pq.Quantity(sfc, units=pq.dimensionless), pq.Quantity(frequencies, units=pq.Hz))
Use this conversion for PSTH and for spike-time correlations. """ ##ADDED bstc_df to cut the first 500 ms of data out for correlations ###conversion of discrete spike times to binary counts from elephant.conversion import BinnedSpikeTrain bins = 1.0 #define the bin size here in ms for item in g_list: for key in channels[item]: bst_list = BinnedSpikeTrain(channels[item][key]['neoSpkTrain500'], binsize = bins*pq.ms, t_start = 650.0*pq.ms, t_stop = 3160*pq.ms) bst_arr = bst_list.to_array() #export binned spike times to an array bst_df = pd.DataFrame(bst_arr).T #turn into a df and transpose (.T) # bst_df.index = np.arange(550,3050,bins) bst_sum = bst_df.apply(np.sum,axis=1) #sum by row across columns # bst_sum.index = np.arange(550,3050,bins) channels[item][key]['binned_spike_list'] = bst_list channels[item][key]['binnedSpikes'] = bst_df channels[item][key]['binnedSpksSum'] = bst_sum bst_arr = None bst_df = None bst_sum = None #%% ###PSTH with binned spike counts #make gaussian kernel with 2 ms SD
def spike_field_coherence(signal, spiketrain, **kwargs): """ Calculates the spike-field coherence between a analog signal(s) and a (binned) spike train. The current implementation makes use of scipy.signal.coherence(). Additional kwargs will will be directly forwarded to scipy.signal.coherence(), except for the axis parameter and the sampling frequency, which will be extracted from the input signals. The spike_field_coherence function receives an analog signal array and either a binned spike train or a spike train containing the original spike times. In case of original spike times the spike train is binned according to the sampling rate of the analog signal array. The AnalogSignal object can contain one or multiple signal traces. In case of multiple signal traces, the spike field coherence is calculated individually for each signal trace and the spike train. Parameters ---------- signal : neo AnalogSignalArray object 'signal' contains n analog signals. spiketrain : SpikeTrain or BinnedSpikeTrain Single spike train to perform the analysis on. The binsize of the binned spike train must match the sampling_rate of signal. KWArgs ------ All KWArgs are passed to scipy.signal.coherence(). Returns ------- coherence : complex Quantity array contains the coherence values calculated for each analog signal trace in combination with the spike train. The first dimension corresponds to the frequency, the second to the number of the signal trace. frequencies : Quantity array contains the frequency values corresponding to the first dimension of the 'coherence' array Example ------- Plot the SFC between a regular spike train at 20 Hz, and two sinusoidal time series at 20 Hz and 23 Hz, respectively. >>> import numpy as np >>> import matplotlib.pyplot as plt >>> from quantities import ms, mV, Hz, kHz >>> import neo, elephant >>> t = pq.Quantity(range(10000),units='ms') >>> f1, f2 = 20. * Hz, 23. * Hz >>> signal = neo.AnalogSignal(np.array([ np.sin(f1 * 2. * np.pi * t.rescale(s)), np.sin(f2 * 2. * np.pi * t.rescale(s))]).T, units=pq.mV, sampling_rate=1. * kHz) >>> spiketrain = neo.SpikeTrain( range(t[0], t[-1], 50), units='ms', t_start=t[0], t_stop=t[-1]) >>> sfc, freqs = elephant.sta.spike_field_coherence( signal, spiketrain, window='boxcar') >>> plt.plot(freqs, sfc[:,0]) >>> plt.plot(freqs, sfc[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('SFC') >>> plt.xlim((0, 60)) >>> plt.show() """ if not hasattr(scipy.signal, 'coherence'): raise AttributeError( 'scipy.signal.coherence is not available. The sfc ' 'function uses scipy.signal.coherence for ' 'the coherence calculation. This function is ' 'available for scipy version 0.16 or newer. ' 'Please update you scipy version.') # spiketrains type check if not isinstance(spiketrain, (SpikeTrain, BinnedSpikeTrain)): raise TypeError( "spiketrain must be of type SpikeTrain or BinnedSpikeTrain, " "not %s." % type(spiketrain)) # checks on analogsignal if not isinstance(signal, AnalogSignalArray): raise TypeError("Signal must be an AnalogSignalArray, not %s." % type(signal)) if len(signal.shape) > 1: # num_signals: number of individual traces in the analog signal num_signals = signal.shape[1] elif len(signal.shape) == 1: num_signals = 1 else: raise ValueError("Empty analog signal.") len_signals = signal.shape[0] # bin spiketrain if necessary if isinstance(spiketrain, SpikeTrain): spiketrain = BinnedSpikeTrain(spiketrain, binsize=signal.sampling_period) # check the start and stop times of signal and spike trains if spiketrain.t_start < signal.t_start: raise ValueError( "The spiketrain starts earlier than the analog signal.") if spiketrain.t_stop > signal.t_stop: raise ValueError("The spiketrain stops later than the analog signal.") # check equal time resolution for both signals if spiketrain.binsize != signal.sampling_period: raise ValueError("The spiketrain and signal must have a " "common sampling frequency / binsize") # calculate how many bins to add on the left of the binned spike train delta_t = spiketrain.t_start - signal.t_start if delta_t % spiketrain.binsize == 0: left_edge = int((delta_t / spiketrain.binsize).magnitude) else: raise ValueError("Incompatible binning of spike train and LFP") right_edge = int(left_edge + spiketrain.num_bins) # duplicate spike trains spiketrain_array = np.zeros((1, len_signals)) spiketrain_array[0, left_edge:right_edge] = spiketrain.to_array() spiketrains_array = np.squeeze( np.repeat(spiketrain_array, repeats=num_signals, axis=0)).transpose() # calculate coherence frequencies, sfc = scipy.signal.coherence( spiketrains_array, signal.magnitude, fs=signal.sampling_rate.rescale('Hz').magnitude, axis=0, **kwargs) return (pq.Quantity(sfc, units=pq.dimensionless), pq.Quantity(frequencies, units=pq.Hz))
from elephant.statistics import mean_firing_rate firing_rate_list = [] for spiketrain in neospiketrain_list: temp_firing_rate = mean_firing_rate(spiketrain.rescale(pq.s), t_start=0.5, t_stop=1.5) firing_rate_list.append(np.asarray(temp_firing_rate)) # %% conversion of discrete spike times to binary counts from elephant.conversion import BinnedSpikeTrain bst_list = BinnedSpikeTrain(del_half_neospiketrain_list, binsize=1.0 * pq.ms, t_start=700.0 * pq.ms, t_stop=3200.0 * pq.ms) bst_arr = bst_list.to_array() # export binned spike times to an array bst_df = pd.DataFrame(bst_arr).T # turn into a df and transpose (.T) bst_sum = bst_df.apply(np.sum, axis=1) # sum by row across columns # plt.figure() #plt.plot(bst_sum) """ Making PSTH for the whole sweep, without first 500 ms omitted """ bst_list_graph = BinnedSpikeTrain(del_neospiketrain_list, binsize=1.0 * pq.ms, t_start=200.0 * pq.ms, t_stop=3200.0 * pq.ms) bst_arr_graph = bst_list_graph.to_array( ) # export binned spike times to an array