def getPulseStats(self): """ Returns a dictionary with combinations of pulse parameters, formatted as (<Pulse Duration>, <Pulse Interval>), as keys and corresponding lists of trial names as values. Trial names are formatted as "TrialX" where X is the trial number of the associated pulse parameter combination. :return: dict """ tempDF = pd.DataFrame() if 'PulseStimulii' in self.nixFile.sections[ 'VibrationStimulii-Processed'].sections: pulseParSecNames = {} for sec in self.nixFile.sections[ 'VibrationStimulii-Processed'].sections[ 'PulseStimulii'].sections: pulsePars = getSecPulsePars(sec) for s in sec.sections: tempS = pd.Series() tempS['Pulse Duration (ms)'] = pulsePars[0] tempS['Pulse Interval (ms)'] = pulsePars[1] tempS['Trial Label'] = s.name tempS['Frequency (Hz)'] = pulsePars[2] tempS['Number of Pulse Repetitions'] = \ float(property2qu(s.props['NumberOfPulseRepetitions']).magnitude) tStart = property2qu(s.props["StimulusStart"])[0] tStart.unit = qu.s tempS['Time of Start of Pulse train (s)'] = simpleFloat( tStart) tempDF = tempDF.append(tempS, ignore_index=True) return tempDF
def sectionDurIntervalTuple(sec, units): if 'PulseDuration' in sec.props: duration = property2qu(sec.props['PulseDuration'])[0] else: return None if 'PulseInterval' in sec.props: interval = property2qu(sec.props['PulseInterval'])[0] else: return None duration.units = units interval.units = units return float(duration), float(interval)
def getSecPulseProps(section, units): if 'PulseDuration' in section: pulseDur = property2qu(section.props['PulseDuration']) pulseDur.units = units else: raise('Pulse Duration not found in ' + section.name) if 'PulseInterval' in section: pulseInt = property2qu(section.props['PulseInterval']) pulseInt.units = units else: raise('Pulse Interval not found in ' + section.name) return float(pulseDur.magnitude), float(pulseInt.magnitude)
def getSecPulsePars(sec): ''' Converts and returns Pulse duration, pulse interval and frequency of pulse stimuli contained in properties of the section "sec" :param sec: an NIX section :return: tuple of three quantities.Quantity objects, (<pulse duration>, <pulse interval>, <frequency>) ''' pulseDur = property2qu(sec.props['PulseDuration']) pulseDur.units = qu.ms pulseInt = property2qu(sec.props['PulseInterval']) pulseInt.units = qu.ms pulseFreq = property2qu(sec.props['Frequency']) pulseFreq.units = qu.Hz return (float(pulseDur.magnitude), float(pulseInt.magnitude), float(pulseFreq.magnitude))
def _getSpikeTrainStartStop(tagType, tagMetadata, Fs): ''' Internal function, don't use ''' stimStart = property2qu(tagMetadata.props['StimulusStart'])[0] stimEnd = property2qu(tagMetadata.props['StimulusEnd'])[0] if tagType == 'DuringStimulus': tStart = stimStart tStop = stimEnd if tagType == 'BeforeStimulus': tStop = stimStart tStart = tStop - Fs if tagType == 'AfterStimulus': tStart = stimEnd tStop = tStart + Fs return tStart, tStop
def sortSegments(self): rawSec = self.nixFile.sections['VibrationStimulii-Raw'] writtenFreqs = property2qu( rawSec.sections['ContinuousStimulii'].props['FrequenciesUsed']) self.hasPulses = False if any([x.name == 'PulseStimulii' for x in rawSec.sections]): writtenPulseDurs = property2qu( rawSec.sections['PulseStimulii'].props['PulseDurations']) writtenPulseIntervals = property2qu( rawSec.sections['PulseStimulii'].props['PulseIntervals']) self.pulseInput = {} self.hasPulses = True def nearestQu(a, a0): return a[np.abs(a - a0).argmin()] def nearestLowerEqQu(a, a0): temp = a[a <= a0] if temp.shape[0]: return nearestQu(temp, a0) else: return nearestQu(a, a0) self.contInput = {} self.backwardISIs = np.empty_like(self.stimDurs) self.forwardISIs = np.empty_like(self.stimDurs) self.backwardISIs[0] = 1 * self.stimDurs.units self.forwardISIs[-1] = 1 * self.stimDurs.units temp = np.diff(self.stimStartInds ) * self.vibrationSignal.sampling_period.simplified self.backwardISIs[1:] = temp self.forwardISIs[:-1] = temp for stimInd in range(len(self.stimDurs)): stimTime = simpleFloat(self.stimStartInds[stimInd] * self.voltageSignal.sampling_period) #if it's a pulse stimulus if (self.stimDurs[stimInd] < 0.5 * qu.s) and self.hasPulses: nearestPulseDur = nearestLowerEqQu(writtenPulseDurs, self.stimDurs[stimInd]) nearestPulseInterval = nearestQu(writtenPulseIntervals, self.forwardISIs[stimInd]) key = (simpleFloat(nearestPulseDur), simpleFloat(nearestPulseInterval)) # if it's the first pulse of the pulse train if (self.backwardISIs[stimInd] > 0.5 * qu.s) and ( self.forwardISIs[stimInd] < 0.5 * qu.s): diff = (nearestPulseInterval - self.forwardISIs[stimInd]) if diff > 6 * qu.ms: print( 'Time: {}; Large difference between estimated and ' 'written values of pulse interval'.format( stimTime)) print( 'Estimated PI: {}; Closest Written PI: {}; Diff: {}' .format(self.forwardISIs[stimInd], nearestPulseInterval, diff)) print('Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') else: self.pulseInput.setdefault(key, []).append([stimInd]) if key in self.pulseInput: # for the intermediate pulses of the pulse train if (self.backwardISIs[stimInd] < 0.5 * qu.s) and ( self.forwardISIs[stimInd] < 0.5 * qu.s): diff = (nearestPulseInterval - self.forwardISIs[stimInd]) if diff > 6 * qu.ms: print( 'Time: {}; Large difference between estimated and ' 'written values of pulse interval'.format( stimTime)) print( 'Estimated PI: {}; Closest Written PI: {}; Diff: {}' .format(self.forwardISIs[stimInd], nearestPulseInterval, diff)) print( 'Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') else: self.pulseInput[key][-1].append(stimInd) # for the last pulse of the pulse train if (self.backwardISIs[stimInd] < 0.5 * qu.s) and ( self.forwardISIs[stimInd] > 0.5 * qu.s): nearestPulseInterval = nearestQu( writtenPulseIntervals, self.backwardISIs[stimInd]) key = (simpleFloat(nearestPulseDur), simpleFloat(nearestPulseInterval)) diff = (nearestPulseInterval - self.backwardISIs[stimInd]) if diff > 6 * qu.ms: print( 'Time: {}; Large difference between estimated and ' 'written values of pulse interval'.format( stimTime)) print( 'Estimated PI: {}; Closest Written PI: {}; Diff: {}' .format(self.backwardISIs[stimInd], nearestPulseInterval, diff)) print( 'Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') else: self.pulseInput[key][-1].append(stimInd) # isolated pulse? else: if (self.backwardISIs[stimInd] > 0.5 * qu.s) and ( self.forwardISIs[stimInd] > 0.5 * qu.s): print('FYI: Isolated Pulse at ' + str(self.stimStartInds[stimInd] * self.voltageSignal.sampling_period)) print('Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') # if it's a continuous stimulus else: nearestFreq = simpleFloat( nearestQu(writtenFreqs, self.stimFreqs[stimInd])) freqDiff = (nearestFreq * qu.Hz) - self.stimFreqs[stimInd] if freqDiff > 20 * qu.Hz: print( 'Time: {}; Large difference between estimated and written frequencies' .format(stimTime)) print( 'Estimated Frequency: {}; Closest Written Freq: {}; Diff: {}' .format(self.stimFreqs[stimInd], nearestFreq, freqDiff)) print('Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') else: self.contInput.setdefault(nearestFreq, []).append(stimInd) if self.hasPulses: for k, v in self.pulseInput.items(): onlyTrain = len(v) == 1 for ind, stims in enumerate(v): if len(stims) == 1: stimInd = stims[0] print('FYI: Isolated Pulse at ' + str(self.stimStartInds[stimInd] * self.voltageSignal.sampling_period)) print('Freq: {}; Duration: {}; Amplitude: {}'.format( self.stimFreqs[stimInd], self.stimDurs[stimInd], self.stimAmps[stimInd])) print('This response will be ignored') self.pulseInput[k].pop(ind) if onlyTrain: self.pulseInput.pop(k)