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 get_spike_waveforms(vm, threshold=0.0*mV, width=10*ms): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. width: the length (in ms) of the snippet extracted, centered at the spike peak. Returns: a neo.core.AnalogSignalArray of membrane potential snippets corresponding to each spike. """ spike_train = threshold_detection(vm,threshold=threshold) # Fix for 0-length spike train issue in elephant. try: len(spike_train) except TypeError: spike_train = neo.core.SpikeTrain([],t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) vm_array = neo.core.AnalogSignalArray(vm,units=vm.units, sampling_rate=vm.sampling_rate) snippets = [vm_array.time_slice(t-width/2,t+width/2) for t in spike_train] return neo.core.AnalogSignalArray(snippets,units=vm.units, sampling_rate=vm.sampling_rate)
def test_threshold_detection(self): # Test whether spikes are extracted at the correct times from # an analog signal. # Load membrane potential simulated using Brian2 # according to make_spike_extraction_test_data.py. curr_dir = os.path.dirname(os.path.realpath(__file__)) npz_file_loc = os.path.join(curr_dir,'spike_extraction_test_data.npz') iom2 = neo.io.PyNNNumpyIO(npz_file_loc) data = iom2.read() vm = data[0].segments[0].analogsignals[0] spike_train = stgen.threshold_detection(vm) try: len(spike_train) except TypeError: # Handles an error in Neo related to some zero length # spike trains being treated as unsized objects. warnings.warn(("The spike train may be an unsized object. This may be related " "to an issue in Neo with some zero-length SpikeTrain objects. " "Bypassing this by creating an empty SpikeTrain object.")) spike_train = neo.core.SpikeTrain([],t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) # Correct values determined previously. true_spike_train = [0.0123, 0.0354, 0.0712, 0.1191, 0.1694, 0.22, 0.2711] # Does threshold_detection gives the correct number of spikes? self.assertEqual(len(spike_train),len(true_spike_train)) # Does threshold_detection gives the correct times for the spikes? try: assert_array_almost_equal(spike_train,spike_train) except AttributeError: # If numpy version too old to have allclose self.assertTrue(np.array_equal(spike_train,spike_train))
def get_spike_waveforms(vm, threshold=0.0 * mV, width=10 * ms): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. width: the length (in ms) of the snippet extracted, centered at the spike peak. Returns: a neo.core.AnalogSignal where each column contains a membrane potential snippets corresponding to one spike. """ spike_train = threshold_detection(vm, threshold=threshold) # Fix for 0-length spike train issue in elephant. try: len(spike_train) except TypeError: spike_train = neo.core.SpikeTrain([], t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) snippets = [ vm.time_slice(t - width / 2, t + width / 2) for t in spike_train ] result = neo.core.AnalogSignal(np.array(snippets).T.squeeze(), units=vm.units, sampling_rate=vm.sampling_rate) return result
def test_threshold_detection(self): # Test whether spikes are extracted at the correct times from # an analog signal. spike_train = stgen.threshold_detection(self.vm) try: len(spike_train) except TypeError: # Handles an error in Neo related to some zero length # spike trains being treated as unsized objects. warnings.warn(( "The spike train may be an unsized object. This may be related " "to an issue in Neo with some zero-length SpikeTrain objects. " "Bypassing this by creating an empty SpikeTrain object.")) spike_train = neo.core.SpikeTrain([], t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) # Does threshold_detection gives the correct number of spikes? self.assertEqual(len(spike_train), len(self.true_time_stamps)) # Does threshold_detection gives the correct times for the spikes? try: assert_array_almost_equal(spike_train, self.true_time_stamps) except AttributeError: # If numpy version too old to have allclose self.assertTrue(np.array_equal(spike_train, self.true_time_stamps))
def get_spike_train(vm, threshold=0.0*mV): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. Returns: a neo.core.SpikeTrain containing the times of spikes. """ spike_train = threshold_detection(vm,threshold=threshold) return spike_train
def get_spike_train(vm, threshold=0.0 * mV): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. Returns: a neo.core.SpikeTrain containing the times of spikes. """ spike_train = threshold_detection(vm, threshold=threshold) return spike_train
def get_spike_waveforms(vm, threshold=0.0*mV, width=10*ms): """ Membrane potential trace (1D numpy array) to matrix of spike snippets (2D numpy array) Inputs: vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. width: the length (in ms) of the snippet extracted, centered at the spike peak. Returns: a neo.core.AnalogSignal where each column contains a membrane potential snippets corresponding to one spike. """ spike_train = threshold_detection(vm, threshold=threshold) # Fix for 0-length spike train issue in elephant. try: assert len(spike_train) != 0 except TypeError: spike_train = neo.core.SpikeTrain([], t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) too_short = True too_long = True # This code checks that you are not asking for a window into an array, # with out of bounds indicies. t = spike_train[0] if t-width/2.0 > 0.0*ms: too_short = False t = spike_train[-1] if t+width/2.0 < vm.times[-1]: too_long = False if not too_short and not too_long: snippets = [vm.time_slice(t-width/2, t+width/2) for t in spike_train] elif too_long: snippets = [vm.time_slice(t-width/2, t) for t in spike_train] elif too_short: snippets = [vm.time_slice(t, t+width/2) for t in spike_train] result = neo.core.AnalogSignal(np.array(snippets).T.squeeze(), units=vm.units, sampling_rate=vm.sampling_rate) return result
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_spike_waveforms(vm, threshold=0.0*mV, width=5*ms): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. width: the length (in ms) of the snippet extracted, centered at the spike peak. Returns: a neo.core.AnalogSignalArray of membrane potential snippets corresponding to each spike. """ spike_train = threshold_detection(vm,threshold=threshold) vm_array = neo.core.AnalogSignalArray(vm,units=vm.units, sampling_rate=vm.sampling_rate) snippets = [vm_array.time_slice(t-width/2,t+width/2) for t in spikes] return neo.core.AnalogSignalArray(snippets,units=vm.units, sampling_rate=vm.sampling_rate)
def allen_format(volts, times, optional_vm=None): ''' Synposis: At its most fundamental level, AllenSDK still calls a single trace a sweep. In otherwords there are no single traces, but there are sweeps of size 1. This is a bit like wrapping unitary objects in iterable containers like [times]. inputs: np.arrays of time series: Specifically a time recording vector, and a membrane potential recording. in floats probably with units striped away outputs: a data frame of Allen features, a very big dump of features as they pertain to each spike in a train. to get a managable data digest we out put features from the middle spike of a spike train. ''' if optional_vm is not None: spike_train = threshold_detection(optional_vm, threshold=0) ext = EphysSweepSetFeatureExtractor([times], [volts]) ext.process_spikes() swp = ext.sweeps()[0] spikes = swp.spikes() if len(spikes) == 0: return (None, None) meaned_features_1 = {} skeys = [skey for skey in spikes[0].keys()] for sk in skeys: if str('isi_type') not in sk: meaned_features_1[sk] = np.mean( [i[sk] for i in spikes if type(i) is not type(str(''))]) allen_features = {} meaned_features_overspikes = {} for s in swp.sweep_feature_keys(): # print(swp.sweep_feature(s)) if str('isi_type') not in s: allen_features[s] = swp.sweep_feature(s) allen_features.update(meaned_features_1) return meaned_features_overspikes, allen_features '''
def get_firing_rate(model, input_current): # inject a test current into the neuron and call it's run() function. # get the spike times using spike_tools.get_spike_times # from the spike times, calculate the firing rate f IC = InjectedCurrent(amp = input_current*pq.pA) params = IC.get_params() model.inject_square_current(params) vm = model.get_membrane_potential() spikes = threshold_detection(vm,threshold=0*pq.mV) if len(spikes): isi_easy = isi(spikes) rate = 1.0/np.mean(isi_easy) if rate == np.nan or np.isnan(rate): rate = 0 rate = rate*pq.Hz else: rate = 0*pq.Hz return rate
def test_threshold_detection(self): # Test whether spikes are extracted at the correct times from # an analog signal. # Load membrane potential simulated using Brian2 # according to make_spike_extraction_test_data.py. curr_dir = os.path.dirname(os.path.realpath(__file__)) npz_file_loc = os.path.join(curr_dir,'spike_extraction_test_data.npz') iom2 = neo.io.PyNNNumpyIO(npz_file_loc) data = iom2.read() vm = data[0].segments[0].analogsignals[0] spike_train = stgen.threshold_detection(vm) # Correct values determined previously. true_spike_train = [0.0123, 0.0354, 0.0712, 0.1191, 0.1694, 0.22, 0.2711] # Does threshold_detection gives the correct number of spikes? assert len(spike_train) == len(true_spike_train) # Does threshold_detection gives the correct times for the spikes? assert np.allclose(spike_train,spike_train)
def get_spike_waveforms(vm, threshold=0.0 * mV, width=5 * ms): """ vm: a neo.core.AnalogSignal corresponding to a membrane potential trace. threshold: the value (in mV) above which vm has to cross for there to be a spike. Scalar float. width: the length (in ms) of the snippet extracted, centered at the spike peak. Returns: a neo.core.AnalogSignalArray of membrane potential snippets corresponding to each spike. """ spike_train = threshold_detection(vm, threshold=threshold) vm_array = neo.core.AnalogSignalArray(vm, units=vm.units, sampling_rate=vm.sampling_rate) snippets = [ vm_array.time_slice(t - width / 2, t + width / 2) for t in spikes ] return neo.core.AnalogSignalArray(snippets, units=vm.units, sampling_rate=vm.sampling_rate)
def test_threshold_detection(self): # Test whether spikes are extracted at the correct times from # an analog signal. spike_train = stgen.threshold_detection(self.vm) try: len(spike_train) except TypeError: # Handles an error in Neo related to some zero length # spike trains being treated as unsized objects. warnings.warn(("The spike train may be an unsized object. This may be related " "to an issue in Neo with some zero-length SpikeTrain objects. " "Bypassing this by creating an empty SpikeTrain object.")) spike_train = neo.core.SpikeTrain([],t_start=spike_train.t_start, t_stop=spike_train.t_stop, units=spike_train.units) # Does threshold_detection gives the correct number of spikes? self.assertEqual(len(spike_train),len(self.true_time_stamps)) # Does threshold_detection gives the correct times for the spikes? try: assert_array_almost_equal(spike_train, self.true_time_stamps) except AttributeError: # If numpy version too old to have allclose self.assertTrue(np.array_equal(spike_train, self.true_time_stamps))
def test_peak_detection_threshold(self): # Test for empty SpikeTrain when threshold is too high result = stgen.threshold_detection(self.vm, threshold=30 * mV) self.assertEqual(len(result), 0)
def get_spike_train(self): thresh = threshold_detection(self.vM) return thresh
def get_spike_count(self): thresh = threshold_detection(self.vM) return len(thresh)
def three_feature_sets_on_static_models(model, unit_test=False, challenging=False): ''' Conventions: variables ending with 15 refer to 1.5 current injection protocols. variables ending with 30 refer to 3.0 current injection protocols. Inputs: NML-DB models, a method designed to be called inside an iteration loop, where a list of models is iterated over, and on each iteration a new model is supplied to this method. Outputs: A dictionary of dataframes, for features sought according to: Druckman, EFEL, AllenSDK ''' ## # wrangle data in preperation for computing # Allen Features ## #import pdb; pdb.set_trace() if type(model) is type(DataTC()): model = model.dtc_to_model() if not hasattr(model, 'vm30'): model.inject_square_current(model.rheobase * 3.0) model.vm30 = model.get_membrane_potential() ['amplitude'] model.inject_square_current() model.vm15 = model.get_membrane_potential() times = np.array([float(t) for t in model.vm30.times]) volts = np.array([float(v) for v in model.vm30]) try: import asciiplotlib as apl fig = apl.figure() fig.plot(times, volts, label="V_{m} (mV), versus time (ms)", width=100, height=80) fig.show() except: pass ## # Allen Features ## #frame_shape,frame_dynamics,per_spike_info, meaned_features_overspikes all_allen_features30, allen_features30 = allen_format( volts, times, optional_vm=model.vm30) #if frame30 is not None: # frame30['protocol'] = 3.0 ## # wrangle data in preperation for computing # Allen Features ## times = np.array([float(t) for t in model.vm15.times]) volts = np.array([float(v) for v in model.vm15]) ## # Allen Features ## all_allen_features15, allen_features15 = allen_format( volts, times, optional_vm=model.vm15) ## # Get Druckman features, this is mainly handled in external files. ## #if model.ir_currents DMTNMLO = dm_test_interoperable.DMTNMLO() if hasattr(model, 'druckmann2013_input_resistance_currents') and not hasattr( model, 'allen'): DMTNMLO.test_setup(None, None, model=model) else: DMTNMLO.test_setup(None, None, model=model, ir_current_limited=True) dm_test_features = DMTNMLO.runTest() ## # Wrangle data to prepare for EFEL feature calculation. ## trace3 = {} trace3['T'] = [float(t) for t in model.vm30.times.rescale('ms')] trace3['V'] = [float(v) for v in model.vm30.magnitude] #temp_vm trace3['stimulus_current'] = [model.druckmann2013_strong_current] if not hasattr(model, 'allen'): trace3['stim_end'] = [trace3['T'][-1]] trace3['stim_start'] = [float(model.protocol['Time_Start'])] else: trace3['stim_end'] = [float(model.protocol['Time_End']) * 1000.0] trace3['stim_start'] = [float(model.protocol['Time_Start']) * 1000.0] traces3 = [ trace3 ] # Now we pass 'traces' to the efel and ask it to calculate the feature# values trace15 = {} trace15['T'] = [float(t) for t in model.vm15.times.rescale('ms')] trace15['V'] = [float(v) for v in model.vm15.magnitude] #temp_vm if not hasattr(model, 'allen'): trace15['stim_end'] = [trace15['T'][-1]] trace15['stim_start'] = [float(model.protocol['Time_Start'])] else: trace15['stim_end'] = [float(model.protocol['Time_End']) * 1000.0] trace15['stim_start'] = [float(model.protocol['Time_Start']) * 1000.0] trace15['stimulus_current'] = [model.druckmann2013_standard_current] trace15['stim_end'] = [trace15['T'][-1]] traces15 = [ trace15 ] # Now we pass 'traces' to the efel and ask it to calculate the feature# values ## # Compute # EFEL features (HBP) ## efel.reset() if len(threshold_detection(model.vm15, threshold=0)): #pass threshold = float( np.max(model.vm15.magnitude) - 0.5 * np.abs(np.std(model.vm15.magnitude))) print(len(threshold_detection(model.vm15, threshold=threshold))) print(threshold, 'threshold', np.max(model.vm15.magnitude), np.min(model.vm15.magnitude)) #efel_15 = efel.getMeanFeatureValues(traces15,list(efel.getFeatureNames()))# else: threshold = float( np.max(model.vm15.magnitude) - 0.2 * np.abs(np.std(model.vm15.magnitude))) efel.setThreshold(threshold) print(len(threshold_detection(model.vm15, threshold=threshold))) print(threshold, 'threshold', np.max(model.vm15.magnitude)) if np.min(model.vm15.magnitude) < 0: efel_15 = efel.getMeanFeatureValues(traces15, list(efel.getFeatureNames())) else: efel_15 = None efel.reset() if len(threshold_detection(model.vm30, threshold=0)): threshold = float( np.max(model.vm30.magnitude) - 0.5 * np.abs(np.std(model.vm30.magnitude))) print(len(threshold_detection(model.vm30, threshold=threshold))) print(threshold, 'threshold', np.max(model.vm30.magnitude), np.min(model.vm30.magnitude)) #efel_30 = efel.getMeanFeatureValues(traces3,list(efel.getFeatureNames())) else: threshold = float( np.max(model.vm30.magnitude) - 0.2 * np.abs(np.std(model.vm30.magnitude))) efel.setThreshold(threshold) print(len(threshold_detection(model.vm15, threshold=threshold))) print(threshold, 'threshold', np.max(model.vm15.magnitude)) if np.min(model.vm30.magnitude) < 0: efel_30 = efel.getMeanFeatureValues(traces3, list(efel.getFeatureNames())) else: efel_30 = None efel.reset() if hasattr(model, 'information'): return { 'model_id': model.name, 'model_information': model.information, 'efel_15': efel_15, 'efel_30': efel_30, 'dm': dm_test_features, 'allen_15': all_allen_features15, 'allen_30': all_allen_features30 } else: return { 'model_id': model.name, 'model_information': 'allen_data', 'efel_15': efel_15, 'efel_30': efel_30, 'dm': dm_test_features, 'allen_15': all_allen_features15, 'allen_30': all_allen_features30 }