def downSampleAnalogSignal(analogSignal, downSampleFactor): ''' Downsamples the input analogsignal, with the downsampled signal having the same t_start as analogsignal :param analogSignal: neo.analogsignal :param downSampleFactor: int, must be at least 1 :return: analogSignalDown, neo.analogsignal with sampling rate = analogsignal.sampling_rate/factor and analogSignalDown.t_start = analogSignal.t_start ''' assert type(downSampleFactor) == int, 'downsample factor must be an int' assert downSampleFactor >= 1, 'downsample factor must be atleast 1' if downSampleFactor == 1: return analogSignal.copy() else: newSamplingRate = analogSignal.sampling_rate / downSampleFactor downSamplingIndices = range(0, analogSignal.shape[0], downSampleFactor) analogSignalMagnitude = analogSignal.magnitude[downSamplingIndices] analogSignalDown = AnalogSignal(signal=analogSignalMagnitude, units=analogSignal.units, sampling_rate=newSamplingRate, t_start=analogSignal.t_start) analogSignalDown = analogSignalDown.reshape( (analogSignalDown.shape[0], )) return analogSignalDown
def setUp(self): self.asiga0 = AnalogSignal(np.array( [np.sin(np.arange(0, 20 * math.pi, 0.1))]).T, units='mV', sampling_rate=10 / ms) self.asiga1 = AnalogSignal(np.array([ np.sin(np.arange(0, 20 * math.pi, 0.1)), np.cos(np.arange(0, 20 * math.pi, 0.1)) ]).T, units='mV', sampling_rate=10 / ms) self.asiga2 = AnalogSignal(np.array([ np.sin(np.arange(0, 20 * math.pi, 0.1)), np.cos(np.arange(0, 20 * math.pi, 0.1)), np.tan(np.arange(0, 20 * math.pi, 0.1)) ]).T, units='mV', sampling_rate=10 / ms) self.st0 = SpikeTrain( [9 * math.pi, 10 * math.pi, 11 * math.pi, 12 * math.pi], units='ms', t_stop=self.asiga0.t_stop) self.lst = [ SpikeTrain([9 * math.pi, 10 * math.pi, 11 * math.pi, 12 * math.pi], units='ms', t_stop=self.asiga1.t_stop), SpikeTrain([30, 35, 40], units='ms', t_stop=self.asiga1.t_stop) ]
def get_APs(self, model): """ Spikes were detected by a crossing of a voltage threshold (-20 mV). :param model: model which provides the waveform to analyse :return: a list of Druckman2013APs """ vm = model.get_membrane_potential() vm_times = vm.times start_time = self.params['injected_square_current']['delay'].rescale( 'sec') end_time = start_time + self.params['injected_square_current'][ 'duration'].rescale('sec') vm = AnalogSignal(vm.magnitude[np.where(vm_times <= end_time)], sampling_period=vm.sampling_period, units=vm.units) try: dvdt = np.array(np.append([0], get_diff( vm, axis=0))) * pq.mV / vm.sampling_period except: dvdt = np.array(np.append( [0], get_diff(vm))) * pq.mV / vm.sampling_period dvdt = AnalogSignal(dvdt, sampling_period=vm.sampling_period) threshold_crosses = threshold_detection( vm, threshold=self.params['threshold']) dvdt_threshold_crosses = threshold_detection( dvdt, threshold=self.params['beginning_threshold']) dvdt_zero_crosses = threshold_detection(dvdt, threshold=0 * pq.mV / pq.ms) vm_chopped, threshold_crosses, ap_beginnings, vm_mag, vm_times = isolate_code_block( threshold_crosses, \ start_time,dvdt_threshold_crosses,dvdt_zero_crosses,vm \ ) ap_waveforms = [] for i, b in enumerate(ap_beginnings): if i != len(ap_beginnings) - 1: waveform = vm_chopped[i + 1] else: # Keep up to 100ms of the last AP waveform = vm_mag[np.where((vm_times >= b) & (vm_times < b + 100.0 * pq.ms))] waveform = AnalogSignal(waveform, units=vm.units, sampling_rate=vm.sampling_rate) ap_waveforms.append(waveform) # Pass in the AP waveforms and the times when they occured self.APs = [] for i, b in enumerate(ap_beginnings): self.APs.append(Druckmann2013AP(ap_waveforms[i], ap_beginnings[i])) return self.APs
def setUp(self): # standard testsignals tlen0 = 100 * pq.s f0 = 20. * pq.Hz fs0 = 1 * pq.ms t0 = np.arange( 0, tlen0.rescale(pq.s).magnitude, fs0.rescale(pq.s).magnitude) * pq.s self.anasig0 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) self.st0 = SpikeTrain( np.arange(0, tlen0.rescale(pq.ms).magnitude, 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.bst0 = BinnedSpikeTrain(self.st0, binsize=fs0) # shortened analogsignals self.anasig1 = self.anasig0.time_slice(1 * pq.s, None) self.anasig2 = self.anasig0.time_slice(None, 99 * pq.s) # increased sampling frequency fs1 = 0.1 * pq.ms self.anasig3 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs1) self.bst1 = BinnedSpikeTrain( self.st0.time_slice(self.anasig3.t_start, self.anasig3.t_stop), binsize=fs1) # analogsignal containing multiple traces self.anasig4 = AnalogSignal( np.array([ np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), np.sin(4 * np.pi * (f0 * t0).simplified.magnitude)]). transpose(), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) # shortened spike train self.st3 = SpikeTrain( np.arange( (tlen0.rescale(pq.ms).magnitude * .25), (tlen0.rescale(pq.ms).magnitude * .75), 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.bst3 = BinnedSpikeTrain(self.st3, binsize=fs0) self.st4 = SpikeTrain(np.arange( (tlen0.rescale(pq.ms).magnitude * .25), (tlen0.rescale(pq.ms).magnitude * .75), 50) * pq.ms, t_start=5 * fs0, t_stop=tlen0 - 5 * fs0) self.bst4 = BinnedSpikeTrain(self.st4, binsize=fs0) # spike train with incompatible binsize self.bst5 = BinnedSpikeTrain(self.st3, binsize=fs0 * 2.) # spike train with same binsize as the analog signal, but with # bin edges not aligned to the time axis of the analog signal self.bst6 = BinnedSpikeTrain( self.st3, binsize=fs0, t_start=4.5 * fs0, t_stop=tlen0 - 4.5 * fs0)
def test_one_spiketrain_empty(self): '''Test for one empty SpikeTrain, but existing spikes in other''' st = [SpikeTrain( [9 * math.pi, 10 * math.pi, 11 * math.pi, 12 * math.pi], units='ms', t_stop=self.asiga1.t_stop), SpikeTrain([], units='ms', t_stop=self.asiga1.t_stop)] STA = sta.spike_triggered_average(self.asiga1, st, (-1 * ms, 1 * ms)) cmp_array = AnalogSignal(np.array([np.zeros(20, dtype=float)]).T, units='mV', sampling_rate=10 / ms) cmp_array = cmp_array / 0. cmp_array.t_start = -1 * ms assert_array_equal(STA.magnitude[:, 1], cmp_array.magnitude[:, 0])
def calibrateSignal(inputSignal, calibString, calibUnitStr, forceUnits=None): if calibString.find(';') > 0: calibStrings = calibString.split(';') elif calibString.find(':') > 0: calibStrings = calibString.split(':') elif all([x.isdigit() or x == '.' for x in calibString]): calibStrings = [calibString] else: raise (ValueError( "Improper Calibration string {}".format(calibString))) ipSignalMag = inputSignal.magnitude.copy() ipSigUnits = inputSignal.units for calibString in calibStrings: calib, startTime, endTime = parseCalibString(calibString, calibUnitStr) if endTime is None: endTime = inputSignal.t_stop if startTime is None: startTime = inputSignal.t_start startIndex = int( (startTime - inputSignal.t_start) * inputSignal.sampling_rate) endIndex = int( (endTime - inputSignal.t_start) * inputSignal.sampling_rate) ipSignalMag[startIndex:endIndex] *= calib.magnitude if forceUnits is not None: ipSigUnits = forceUnits else: if ipSigUnits == qu.Quantity(1): ipSigUnits = calib.units elif ipSigUnits != calib.units: raise (Exception('CalibStrings given don\'t have the same units')) outputSignal = AnalogSignal(signal=ipSignalMag, units=ipSigUnits, sampling_rate=inputSignal.sampling_rate, t_start=inputSignal.t_start) outputSignal = outputSignal.reshape((outputSignal.shape[0], )) return outputSignal
def fetch_waveform_as_AnalogSignal(self, waveform_id, resolution_ms=0.01, units="mV"): #print('gets to b') # If signal not in cache if waveform_id not in self.waveform_signals: # Load api URL into Python #import pdb; pdb.set_trace( #import pdb; pdb.set_trace() data = self.read_api_url(self.api_url + "waveform?id=" + str(waveform_id)) # Get time and signal values (from CSV format) t = np.array(data["Times"].split(','), float) signal = np.array(data["Variable_Values"].split(','), float) # Interpolate to regularly sampled series (API returns irregularly sampled) sig = interp1d(t, signal, fill_value="extrapolate") signal = sig(np.arange(min(t), max(t), resolution_ms)) # Convert to neo.AnalogSignal signal = AnalogSignal(signal, units=units, sampling_period=resolution_ms * quantities.ms) starts_from_ss = next( w for w in self.waveforms if w["ID"] == waveform_id)["Starts_From_Steady_State"] == 1 if starts_from_ss: rest_wave = self.get_steady_state_waveform() t = np.concatenate( (rest_wave.times, signal.times + rest_wave.t_stop)) * quantities.s v = np.concatenate( (np.array(rest_wave), np.array(signal))) * quantities.mV signal = AnalogSignal(v, units=units, sampling_period=resolution_ms * quantities.ms) self.waveform_signals[waveform_id] = signal return self.waveform_signals[waveform_id]
def test_one_spiketrain_empty(self): '''Test for one empty SpikeTrain, but existing spikes in other''' st = [ SpikeTrain([9 * math.pi, 10 * math.pi, 11 * math.pi, 12 * math.pi], units='ms', t_stop=self.asiga1.t_stop), SpikeTrain([], units='ms', t_stop=self.asiga1.t_stop) ] STA = sta.spike_triggered_average(self.asiga1, st, (-1 * ms, 1 * ms)) cmp_array = AnalogSignal(np.array([np.zeros(20, dtype=float)]).T, units='mV', sampling_rate=10 / ms) cmp_array = cmp_array / 0. cmp_array.t_start = -1 * ms assert_array_equal(STA.magnitude[:, 1], cmp_array.magnitude[:, 0])
def inject_square_current(self, current): import re if 'injected_square_current' in current.keys(): c = current['injected_square_current'] else: c = current c['delay'] = re.sub('\ ms$', '', str(c['delay'])) # take delay c['duration'] = re.sub('\ ms$', '', str(c['duration'])) c['amplitude'] = re.sub('\ pA$', '', str(c['amplitude'])) stop = float(c['delay']) + float(c['duration']) start = float(c['delay']) duration = float(c['duration']) amplitude = float(c['amplitude']) / 1000.0 self.glif.dt = 0.001 dt = self.glif.dt stim = [0.0] * int(start) + [amplitude ] * int(duration) + [0.0] * int(stop) #self.glif.init_voltage = -0.0065 self.results = self.glif.run(stim) vm = self.results['voltage'] if len(self.results['interpolated_spike_voltage']) > 0: isv = self.results['interpolated_spike_voltage'].tolist()[0] vm = list(map(lambda x: isv if np.isnan(x) else x, vm)) vms = AnalogSignal(vm, units=V, sampling_period=dt * s) return vms
def wrap_known_i(self, i, times): everything = self.attrs if 'current_inj' in everything.keys(): everything.pop('current_inj', None) if 'celltype' in everything.keys(): everything.pop('celltype', None) two_thousand_and_three = False if two_thousand_and_three: v = AnalogSignal(get_2003_vm(i, times, **reduced), units=pq.mV, sampling_period=0.25 * pq.ms) else: v = AnalogSignal(get_vm_known_i(i, times, **everything), units=pq.mV, sampling_period=(times[1] - times[0]) * pq.ms) thresh = threshold_detection(v, 0 * pq.mV) return v
def get_trough(self): peak_v, peak_t = self.get_peak() post_peak_waveform = self.waveform.magnitude[np.where( self.waveform.times > (peak_t - self.begin_time))] post_peak_waveform = AnalogSignal( post_peak_waveform, units=self.waveform.units, sampling_period=self.waveform.sampling_period) value = post_peak_waveform.min() time = peak_t + post_peak_waveform.times[np.where( post_peak_waveform.magnitude == value)[0]] time = time[0] time.units = pq.ms return value, time
def test_rescale(): epctarg = Epoch([1.1, 1.4] * pq.ms, # TODO: Shouldn't this result in an error? durations=[20, 40, 50] * pq.ns, labels=np.array(['test epoch 1 1', 'test epoch 1 2', 'test epoch 1 3', 'test epoch 2 1', 'test epoch 2 2', 'test epoch 2 3'], dtype='S'), array_annotations={'a': np.array(['1.1', '1.4'])}) print_attributes_of_object(epctarg) print_attributes_of_object(epctarg.rescale(pq.s)) evt = Event([1.1, 1.5, 1.7] * pq.ms, labels=np.array(['test event 1', 'test event 2', 'test event 3'], dtype='S'), array_annotations={'a': np.array(['1.1', '1.5', '1.7'])}) print_attributes_of_object(evt) print_attributes_of_object(evt.rescale(pq.s)) print(evt.rescale(pq.s).units) print(type(epctarg.times)) data = range(10) rate = 1000 * pq.Hz signal = AnalogSignal(data, sampling_rate=rate, units="mV", array_annotations={'b': np.array(['a'])}) print_attributes_of_object(signal) print_attributes_of_object(signal.rescale(pq.V)) print_annotations_of_object(signal.rescale(pq.V)) waveforms1 = np.array([[[0., 1.], [0.1, 1.1]], [[2., 3.], [2.1, 3.1]], [[4., 5.], [4.1, 5.1]]]) * pq.mV data1 = np.array([3, 4, 5]) data2quant = np.array([4.5, 8, 9]) * pq.s data1quant = data1 * pq.s train1 = SpikeTrain(data1quant, waveforms=waveforms1, name='n', arb='arbb', t_stop=10.0 * pq.s, array_annotations={'a': np.array([9, 8, 7])}) print_attributes_of_object(train1) print_attributes_of_object(train1.rescale(pq.ms))
def instantaneous_firing_rate(segment, begin, end): """Computed in bins of 0.1 ms """ bins = np.arange(begin, end, 0.1) hist, _ = np.histogram(segment.spiketrains[0].time_slice(begin, end), bins) for st in segment.spiketrains[1:]: h, _ = np.histogram(st.time_slice(begin, end), bins) hist += h return AnalogSignal(hist, sampling_period=0.1*ms, units=dimensionless, channel_index=0, name="Spike count")
def downSampleVibSignal(self): self.downSamplingFactor = int( round(self.vibrationSignal.sampling_rate / (4 * self.maximumFreq))) newSamplingRate = self.vibrationSignal.sampling_rate / self.downSamplingFactor downSamplingIndices = range(0, self.vibrationSignal.shape[0], self.downSamplingFactor) vibSigDownMag = self.vibrationSignal.magnitude[downSamplingIndices] vibSigDownMag -= np.median(vibSigDownMag) self.vibrationSignalDownStdDev = np.std( vibSigDownMag) * self.vibrationSignal.units temp = AnalogSignal(signal=vibSigDownMag, units=self.vibrationSignal.units, sampling_rate=newSamplingRate, t_start=self.vibrationSignal.t_start) self.vibrationSignalDown = temp.reshape((temp.shape[0], ))
def t_signal(signal): rescale = (signal.base / gain) + offset #rescale=signal.base out = AnalogSignal(rescale, units=signal.units, name=signal.name, sampling_rate=signal.sampling_rate, t_start=signal.t_start, channel_index=signal.channel_index) return out
def downSampleVoltageSignal(self, downSamplingFactor=None): if downSamplingFactor is None: downSamplingFactor = self.downSamplingFactor newSamplingRate = self.voltageSignal.sampling_rate / downSamplingFactor downSamplingIndices = range(0, self.voltageSignal.shape[0], downSamplingFactor) voltageSignalDown = AnalogSignal( signal=self.voltageSignal.magnitude[downSamplingIndices], units=self.voltageSignal.units, sampling_rate=newSamplingRate, t_start=self.voltageSignal.t_start) voltageSignalDown = voltageSignalDown.reshape( (voltageSignalDown.shape[0], )) return voltageSignalDown
def mV(pA_signal, clx_rescale=2): #XXX dep base = pA_signal.base out = AnalogSignal( base / clx_rescale, units='mV', name=pA_signal.name, sampling_rate=pA_signal.sampling_rate, t_start=pA_signal.t_start, #*0, channel_index=pA_signal.channel_index) return out #FIXME the raw for the abf file seems to be pA no matter what to get mV divide by two?!
def configure_inhomogeneous_poisson_process(self): self._configure() if self.refractory_period is not None: if not isinstance(self.refractory_period, pq.unitquantity.UnitTime): self.refractory_period *= pq.ms self.rate = _assert_shape(self.rate, np.ones(self._time_shape)) self.rate = np.reshape(self.rate, (self.time_length, self._size)) self.rate = AnalogSignal(self.rate * pq.Hz, sampling_period=self.dt, t_start=self.t_start) self._configured = True
def get_membrane_potential(self): """Must return a neo.core.AnalogSignal. And must destroy the hoc vectors that comprise it. """ if type(self.vM) is type(None): v = get_vm(**self.attrs) self.vM = AnalogSignal(v, units=pq.mV, sampling_period=0.01 * pq.ms) return self.vM
def _backend_run(self): results = {} if len(self.attrs) > 1: v = get_vm(**self.attrs) else: v = get_vm(self.attrs) self.vM = AnalogSignal(v, units=voltage_units, sampling_period=0.25 * pq.ms) results['vm'] = self.vM.magnitude results['t'] = self.vM.times results['run_number'] = results.get('run_number', 0) + 1 return results
def inject_direct_current(self, I): """ Inputs: current : a dictionary with exactly three items, whose keys are: 'amplitude', 'delay', 'duration' Example: current = {'amplitude':float*pq.pA, 'delay':float*pq.ms, 'duration':float*pq.ms}} where \'pq\' is a physical unit representation, implemented by casting float values to the quanitities \'type\'. Description: A parameterized means of applying current injection into defined Currently only single section neuronal models are supported, the neurite section is understood to be simply the soma. """ attrs = self.attrs if attrs is None: attrs = self.default_attrs self.attrs = attrs self.attrs['I'] = np.array(I) self.attrs['celltype'] = int(round(self.attrs['celltype'])) everything = copy.copy(self.attrs) if 'current_inj' in everything.keys(): everything.pop('current_inj', None) if np.bool_(self.attrs['celltype'] <= 3): everything.pop('celltype', None) v = get_vm_one_two_three(**everything) else: if np.bool_(self.attrs['celltype'] == 4): everything.pop('celltype', None) v = get_vm_four(**everything) if np.bool_(self.attrs['celltype'] == 5): everything.pop('celltype', None) v = get_vm_five(**everything) if np.bool_(self.attrs['celltype'] == 6): everything.pop('celltype', None) if 'I' in self.attrs.keys(): everything.pop('I', None) v = get_vm_six(self.attrs['I'], **everything) if np.bool_(self.attrs['celltype'] == 7): everything.pop('celltype', None) v = get_vm_seven(**everything) if 'I' in self.attrs.keys(): self.attrs.pop('I', None) self.vM = AnalogSignal(v, units=pq.mV, sampling_period=0.25 * pq.ms) return self.vM
def test_all_spiketrains_empty(self): st = SpikeTrain([], units='ms', t_stop=self.asiga1.t_stop) with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") # Trigger warnings. STA = sta.spike_triggered_average( self.asiga1, st, (-1 * ms, 1 * ms)) self.assertEqual("No spike at all was either found or used " "for averaging", str(w[-1].message)) nan_array = np.empty(20) nan_array.fill(np.nan) cmp_array = AnalogSignal(np.array([nan_array, nan_array]).T, units='mV', sampling_rate=10 / ms) assert_array_equal(STA.magnitude, cmp_array.magnitude)
def rates_to_spikes( rates, t_start, t_stop, variation=False): """ Generate spike train with homogenous or inhomogenous Poisson generator :param rates: an array or a float of quantities :param t_start: time to start spike train :param t_stop: time where the spike train stop :param variation: Boolean for variation of rate :return: one or multiple spike train """ if variation: # the case where the variation of the rate is include # We generate the inhomogenous poisson if len(rates.shape) == 1: # the case where we have only one rate signal = AnalogSignal(rates, t_start=t_start, sampling_period=(t_stop-t_start)/rates.shape[-1]) result = [inhomogeneous_poisson_process(signal,as_array=True)] return np.array(result) else : # the case where we have multiple rates result = [] for rate in rates: signal = AnalogSignal(rate, t_start=t_start, sampling_period=(t_stop - t_start) / rates.shape[-1]) result.append(inhomogeneous_poisson_process(signal,as_array=True)) return np.array(result) else: # the case we have only the rate # We generate the homogenous poisson if len(rates.shape) ==0: # the case where we have only one rate result = np.array([homogeneous_poisson_process(rate=rates, t_start=t_start, t_stop=t_stop, as_array=True)]) else: # the case where we have multiple rates result = [] for rate in rates: result.append(homogeneous_poisson_process(rate=rate, t_start=t_start, t_stop=t_stop, as_array=True)) return np.array(result)
def _backend_run(self): results = {} #print(self.attrs,'is attributes the empty list?') if len(self.attrs) > 1: v = get_vm(**self.attrs) else: v = get_vm(self.attrs) self.vM = AnalogSignal(v, units=voltage_units, sampling_period=0.01 * pq.ms) results['vm'] = self.vM.magnitude results['t'] = self.vM.times results['run_number'] = results.get('run_number', 0) + 1 return results
def test_spike_triggered_average_with_n_spikes_on_constant_function(self): """Signal should average to the input""" const = 13.8 x = const * np.ones(201) asiga = AnalogSignal( np.array([x]).T, units='mV', sampling_rate=10 / ms) st = SpikeTrain([3, 5.6, 7, 7.1, 16, 16.3], units='ms', t_stop=20) window_starttime = -2 * ms window_endtime = 2 * ms STA = sta.spike_triggered_average( asiga, st, (window_starttime, window_endtime)) a = int(((window_endtime - window_starttime) * asiga.sampling_rate).simplified) cutout = asiga[0: a] cutout.t_start = window_starttime assert_array_almost_equal(STA, cutout, 12)
def setUp(self): tlen0 = 100 * pq.s f0 = 20. * pq.Hz fs0 = 1 * pq.ms t0 = np.arange( 0, tlen0.rescale(pq.s).magnitude, fs0.rescale(pq.s).magnitude) * pq.s self.anasig0 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) self.st0 = SpikeTrain( np.arange(50, tlen0.rescale(pq.ms).magnitude - 50, 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.st1 = SpikeTrain( [100., 100.1, 100.2, 100.3, 100.9, 101.] * pq.ms, t_start=0 * pq.ms, t_stop=tlen0)
def test_only_one_spike(self): """The output should be the same as the input""" x = np.arange(0, 20, 0.1) y = x**2 sr = 10 / ms z = AnalogSignal(np.array([y]).T, units='mV', sampling_rate=sr) spiketime = 8 * ms spiketime_in_ms = int((spiketime / ms).simplified) st = SpikeTrain([spiketime_in_ms], units='ms', t_stop=20) window_starttime = -3 * ms window_endtime = 5 * ms STA = sta.spike_triggered_average( z, st, (window_starttime, window_endtime)) cutout = z[int(((spiketime + window_starttime) * sr).simplified): int(((spiketime + window_endtime) * sr).simplified)] cutout.t_start = window_starttime assert_array_equal(STA, cutout)
def psth(spike_list, bin_length, normalize=True): """ The function returns the psth of the spiketrains with bin length bin_length. Parameters ---------- spike_list : list(SpikeTrain ) The list of spike trains. They are assumed to start and end at the same time. bin_length : float (ms) Bin length. normalized : bool If true the psth will return the instantenous firing rate, if False it will return spike count per bin. Returns ------- psth : AnalogSignal The PSTH of the spiketrain. Note ---- The spiketrains are assumed to start and stop at the same time! """ t_start = round(spike_list[0].t_start.rescale(qt.ms), 5) t_stop = round(spike_list[0].t_stop.rescale(qt.ms), 5) num_bins = int(round((t_stop - t_start) / bin_length)) r = (float(t_start), float(t_stop)) for sp in spike_list: assert len(numpy.histogram(sp, bins=num_bins, range=r)[0]) == num_bins normalizer = 1.0 if normalize: normalizer = (bin_length / 1000.0) h = [ AnalogSignal(numpy.histogram(sp, bins=num_bins, range=r)[0] / normalizer, t_start=t_start * qt.ms, sampling_period=bin_length * qt.ms, units=munits.spike_per_sec) for sp in spike_list ] return h
def setUp(self): # standard testsignals tlen0 = 100 * pq.s f0 = 20. * pq.Hz fs0 = 1 * pq.ms t0 = np.arange( 0, tlen0.rescale(pq.s).magnitude, fs0.rescale(pq.s).magnitude) * pq.s self.anasig0 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) self.st0 = SpikeTrain( np.arange(0, tlen0.rescale(pq.ms).magnitude, 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.bst0 = BinnedSpikeTrain(self.st0, bin_size=fs0) def test_old_scipy_version(self): self.assertRaises(AttributeError, sta.spike_field_coherence, self.anasig0, self.bst0)
def LPFilterKaiser(signal, cutoff=100, transitionWidth=40, rippleDB=20): cutoff *= qu.Hz nyqFreq = signal.sampling_rate / 2 transitionWidth = transitionWidth * qu.Hz N, beta = kaiserord(rippleDB, transitionWidth / nyqFreq) tapsLP = firwin(N, cutoff / nyqFreq, window=('kaiser', beta)) delay = (N - 1) * 0.5 * signal.sampling_period filteredSignal = AnalogSignal(signal=lfilter(tapsLP, 1.0, signal.magnitude), sampling_rate=signal.sampling_rate, units=signal.units, t_start=signal.t_start - delay) return delay, filteredSignal
def get_membrane_potential(self): """Must return a neo.core.AnalogSignal. And must destroy the hoc vectors that comprise it. """ threshold = self.results['threshold'] interpolated_spike_times = self.results['interpolated_spike_times'] interpolated_spike_thresholds = self.results[ 'interpolated_spike_threshold'] grid_spike_indices = self.results['spike_time_steps'] grid_spike_times = self.results['grid_spike_times'] after_spike_currents = self.results['AScurrents'] vm = self.results['voltage'] if len(self.results['interpolated_spike_voltage']) > 0: isv = self.results['interpolated_spike_voltage'].tolist()[0] vm = list(map(lambda x: isv if np.isnan(x) else x, vm)) dt = self.glif.dt vms = AnalogSignal(vm, units=mV, sampling_period=dt * ms) return vms
class sfc_TestCase_new_scipy(unittest.TestCase): def setUp(self): # standard testsignals tlen0 = 100 * pq.s f0 = 20. * pq.Hz fs0 = 1 * pq.ms t0 = np.arange( 0, tlen0.rescale(pq.s).magnitude, fs0.rescale(pq.s).magnitude) * pq.s self.anasig0 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) self.st0 = SpikeTrain( np.arange(0, tlen0.rescale(pq.ms).magnitude, 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.bst0 = BinnedSpikeTrain(self.st0, binsize=fs0) # shortened analogsignals self.anasig1 = self.anasig0.time_slice(1 * pq.s, None) self.anasig2 = self.anasig0.time_slice(None, 99 * pq.s) # increased sampling frequency fs1 = 0.1 * pq.ms self.anasig3 = AnalogSignal( np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs1) self.bst1 = BinnedSpikeTrain( self.st0.time_slice(self.anasig3.t_start, self.anasig3.t_stop), binsize=fs1) # analogsignal containing multiple traces self.anasig4 = AnalogSignal( np.array([ np.sin(2 * np.pi * (f0 * t0).simplified.magnitude), np.sin(4 * np.pi * (f0 * t0).simplified.magnitude)]). transpose(), units=pq.mV, t_start=0 * pq.ms, sampling_period=fs0) # shortened spike train self.st3 = SpikeTrain( np.arange( (tlen0.rescale(pq.ms).magnitude * .25), (tlen0.rescale(pq.ms).magnitude * .75), 50) * pq.ms, t_start=0 * pq.ms, t_stop=tlen0) self.bst3 = BinnedSpikeTrain(self.st3, binsize=fs0) self.st4 = SpikeTrain(np.arange( (tlen0.rescale(pq.ms).magnitude * .25), (tlen0.rescale(pq.ms).magnitude * .75), 50) * pq.ms, t_start=5 * fs0, t_stop=tlen0 - 5 * fs0) self.bst4 = BinnedSpikeTrain(self.st4, binsize=fs0) # spike train with incompatible binsize self.bst5 = BinnedSpikeTrain(self.st3, binsize=fs0 * 2.) # spike train with same binsize as the analog signal, but with # bin edges not aligned to the time axis of the analog signal self.bst6 = BinnedSpikeTrain( self.st3, binsize=fs0, t_start=4.5 * fs0, t_stop=tlen0 - 4.5 * fs0) # ========================================================================= # Tests for correct input handling # ========================================================================= def test_wrong_input_type(self): self.assertRaises(TypeError, sta.spike_field_coherence, np.array([1, 2, 3]), self.bst0) self.assertRaises(TypeError, sta.spike_field_coherence, self.anasig0, [1, 2, 3]) self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig0.duplicate_with_new_array([]), self.bst0) def test_start_stop_times_out_of_range(self): self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig1, self.bst0) self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig2, self.bst0) def test_non_matching_input_binning(self): self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig0, self.bst1) def test_incompatible_spiketrain_analogsignal(self): # These spike trains have incompatible binning (binsize or alignment to # time axis of analog signal) self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig0, self.bst5) self.assertRaises(ValueError, sta.spike_field_coherence, self.anasig0, self.bst6) def test_signal_dimensions(self): # single analogsignal trace and single spike train s_single, f_single = sta.spike_field_coherence(self.anasig0, self.bst0) self.assertEqual(len(f_single.shape), 1) self.assertEqual(len(s_single.shape), 2) # multiple analogsignal traces and single spike train s_multi, f_multi = sta.spike_field_coherence(self.anasig4, self.bst0) self.assertEqual(len(f_multi.shape), 1) self.assertEqual(len(s_multi.shape), 2) # frequencies are identical since same sampling frequency was used # in both cases and data length is the same assert_array_equal(f_single, f_multi) # coherences of s_single and first signal in s_multi are identical, # since first analogsignal trace in anasig4 is same as in anasig0 assert_array_equal(s_single[:, 0], s_multi[:, 0]) def test_non_binned_spiketrain_input(self): s, f = sta.spike_field_coherence(self.anasig0, self.st0) f_ind = np.where(f >= 19.)[0][0] max_ind = np.argmax(s[1:]) + 1 self.assertEqual(f_ind, max_ind) self.assertAlmostEqual(s[f_ind], 1., delta=0.01) # ========================================================================= # Tests for correct return values # ========================================================================= def test_spike_field_coherence_perfect_coherence(self): # check for detection of 20Hz peak in anasig0/bst0 s, f = sta.spike_field_coherence( self.anasig0, self.bst0, window='boxcar') f_ind = np.where(f >= 19.)[0][0] max_ind = np.argmax(s[1:]) + 1 self.assertEqual(f_ind, max_ind) self.assertAlmostEqual(s[f_ind], 1., delta=0.01) def test_output_frequencies(self): nfft = 256 _, f = sta.spike_field_coherence(self.anasig3, self.bst1, nfft=nfft) # check number of frequency samples self.assertEqual(len(f), nfft / 2 + 1) # check values of frequency samples assert_array_almost_equal( f, np.linspace( 0, self.anasig3.sampling_rate.rescale('Hz').magnitude / 2, nfft / 2 + 1) * pq.Hz) def test_short_spiketrain(self): # this spike train has the same length as anasig0 s1, f1 = sta.spike_field_coherence( self.anasig0, self.bst3, window='boxcar') # this spike train has the same spikes as above, but is shorter than # anasig0 s2, f2 = sta.spike_field_coherence( self.anasig0, self.bst4, window='boxcar') # the results above should be the same, nevertheless assert_array_equal(s1.magnitude, s2.magnitude) assert_array_equal(f1.magnitude, f2.magnitude)