Source code for sparkle.stim.abstract_component

import cPickle
import uuid


[docs]class AbstractStimulusComponent(object): """Represents a single component of a complete summed stimulus""" name = 'unknown' protocol = False explore = False _start_time = None _duration = .01 # in seconds _intensity = 20 # in dB SPL _risefall = 0.003 def __init__(self): self.idnum = uuid.uuid1()
[docs] def duration(self): return self._duration
[docs] def setDuration(self, dur): self._duration = dur
[docs] def intensity(self): return self._intensity
[docs] def setIntensity(self, intensity): self._intensity = intensity
[docs] def risefall(self): return self._risefall
[docs] def setRisefall(self, risefall): self._risefall = risefall
[docs] def set(self, param, value): setattr(self, '_'+param, value)
[docs] def amplitude(self, caldb, calv, atten=0): """Calculates the voltage amplitude for this stimulus, using internal intensity value and the given reference intensity & voltage :param caldb: calibration intensity in dbSPL :type caldb: float :param calv: calibration voltage that was used to record the intensity provided :type calv: float """ amp = (10 ** (float(self._intensity+atten-caldb)/20)*calv) return amp
[docs] def signal(self, fs, atten, caldb, calv): """Creates a signal representation of this stimulus, in the form of a vector of numbers representing electric potential. caldb and calv are used to determine the amplitude of the signal. Must be implemented by subclass :param fs: Generation samplerate (Hz) at which this signal will be output :type fs: int :param atten: actually just 0 for now? :param caldb: calibration intensity in dbSPL :type caldb: float :param calv: calibration voltage that was used to record the intensity provided :type calv: float """ raise NotImplementedError
[docs] def verify(self, **kwargs): """Checks this component for invalidating conditions :returns: str -- message if error, 0 otherwise """ if 'duration' in kwargs: if kwargs['duration'] < self._duration: return "Window size must equal or exceed stimulus length" if self._risefall > self._duration: return "Rise and fall times exceed component duration" return 0
[docs] def auto_details(self): """A collection of the parameter names that are available to be set using auto-paramter manipulation. Subclasses should re-implement and add to this list :returns: dict<dict> -- {'parametername': {'label':str, 'unit':str, 'min':float, 'max':float},} """ return {'duration':{'unit':'s', 'min':0., 'max':3.}, 'intensity':{'unit':'dB SPL', 'min':0, 'max':120}, 'risefall':{'unit':'s', 'min':0, 'max':0.1}}
[docs] def stateDict(self): """Saves internal values to be loaded later :returns: dict -- {'parametername': value, ...} """ state = { 'duration' : self._duration, 'intensity' : self._intensity, 'risefall' : self._risefall, 'stim_type' : self.name } return state
[docs] def loadState(self, state): """Loads previously saved values to this component. :param state: return value from `stateDict` :type state: dict """ self._duration = state['duration'] self._intensity = state['intensity'] self._risefall = state['risefall']
[docs] def serialize(self): return cPickle.dumps(self)
[docs] def clean(self): pass
@staticmethod
[docs] def deserialize(stream): return cPickle.loads(stream)
def __repr__(self): return self.__class__.__name__ + ':' + str(self.idnum) def __eq__(self, other): if self.idnum == other.idnum: return True else: return False def __ne__(self, other): if self.idnum != other.idnum: return True else: return False