def _configured(self, params, sinkParams): self._spikeLength = int(self._spikeDuration * params['fs']) sinkParams['spikeLength'] = self._spikeLength super()._configured(params, sinkParams) self._lastSpike = np.zeros(self._channels) self._buffer = misc.CircularBuffer( (self._channels, int(self._fs * 10)))
def _configured(self, params, sinkParams): super()._configured(params, sinkParams) if self._fs < self._fsOut: raise ValueError('`fsOut` should be >= `fs`') if self._fs != self._fsOut: # use the Fraction class to determine the smallest number of input # and output samples to yield the required downsampling ratio frac = (fractions.Fraction(self._fs) / fractions.Fraction(self._fsOut)) self._nIn = frac.numerator self._nOut = frac.denominator if self._nIn > self._fs * 5: raise ValueError('Numerator of `fs`/`fsOut` is too large') self._buffer = misc.CircularBuffer( (self._channels, int(self._fs * 10)))
def __init__(self, channels, fs, samples, name=None, range=(-10.,10.), regenerate=False, dataNeeded=None, dataChunk=5, onbrdBufDuration=5e-3, bufDuration=30, accurateFS=True, timebaseSrc=None, timebaseRate=None, startTrigger=None): ''' Args: channels (str): Example: '/dev1/ao0' or '/dev2/ao0:1' fs (float): Output sampling rate. Depending on the timebase clock, device might not be able to generate the requested rate accurately. samples (int): Number of samples to output from the device. If set to numpy.inf, task will go into infinite samples mode. name (str): Optional name for the task. range (tuple of float): Output voltage range. This adjusts the output DAC for the best quantization resolution possible. regenerate (bool): If True, task will output the indicated number of samples periodically until stopped. dataNeeded (callable): In infinite samples mode, this function is called before starting the task with an empty buffer or before sample generation reaches end of the buffer. dataChunk (float): In infinite samples mode, how long in seconds should be left to the end of buffer until the `dataNeeded` event is called. onbrdBufDuration (float): In infinite samples mode, deteremines how long should the onboard buffer be in seconds. This value affects the speed at which samples are transferred from software buffer to onboard buffer and is crucial when fast modifications to the buffer are needed. However, this only matters when using a PCIe DAQ model and not for a USB model. The actual buffer size depends on the specified sampling rate and will be clipped between 2 and 8191 samples. bufDuration (float): In infinite samples mode, determines how long should the software buffer be in seconds. The actual buffer size depends on the specified sampling rate. accurateFS (bool): If True, when device is not able to generate the requested sampling frequency accurately, the task will fail and a ValueError will be raised. If False, an inaccurate sampling frequency will only be reported with a warning. timebaseSrc (str): The terminal to use as the timebase for the sample clock. When multiple DAQ devices are connected via an RTSI cable, this value can be used to synchronize their sampling in order to minimize long term offset caused by clock jitter. See the following link for information on terminals: zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/termnames timebaseRate (float): The rate of the specified `timebaseSrc` in Hz. This value is only needed when using an external timebase. startTrigger (str): Configures the task to begin output generation on rising edge of a digital signal. Note that the task should have already been started for the trigger to work. See the following link for information on terminals: zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/termnames ''' super().__init__(channels, fs, samples, name) if samples==np.inf and regenerate: raise ValueError('In %s task, cannot regenerate infinite number of ' 'samples' % self.name) if SIM and samples!=np.inf: raise NotImplementedError('AnalogOutput is not yet implemented for ' 'finite samples in `SIM` mode') if not SIM: self._task.CreateAOVoltageChan(self.channels, '', *range, mx.DAQmx_Val_Volts, '') self._nsOffset = 0 self._regenerate = regenerate self._dataNeeded = misc.Event(dataNeeded, singleCallback=True) self._dataChunk = dataChunk if samples==np.inf: bufSize = int(np.ceil(fs*bufDuration)) if not SIM: self._task.CfgSampClkTiming('', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, 0) self._task.SetWriteRegenMode(mx.DAQmx_Val_DoNotAllowRegen) onbrdBufSize = int(np.clip(np.ceil(fs*onbrdBufDuration), 2, 8191)) self._task.SetBufOutputOnbrdBufSize(onbrdBufSize) self._task.SetBufOutputBufSize(bufSize) # this callback acts more like a timer, it doesn't matter after # how many samples is it called, it just has to happen before # sample generation reaches the end of buffer self._callbackPtr = mx.DAQmxEveryNSamplesEventCallbackPtr( self._callback) self._task.RegisterEveryNSamplesEvent( mx.DAQmx_Val_Transferred_From_Buffer, int(dataChunk*fs/2), 0, self._callbackPtr, None) elif regenerate: self._task.CfgSampClkTiming('', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, samples) self._task.SetWriteRegenMode(mx.DAQmx_Val_AllowRegen) else: self._task.CfgSampClkTiming('', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_FiniteSamps, samples) self._postInit(accurateFS, timebaseSrc, timebaseRate, startTrigger) if SIM: self._simBuffer = misc.CircularBuffer((self.lineCount, bufSize)) self._simInterval = 10e-3 # set simulated generation interval self._simSink = None self._simSinkMap = None
def _configured(self, params, sinkParams): super()._configured(params, sinkParams) self._buffer = misc.CircularBuffer( (self._channels, int(self._fs * 10)))
def __init__(self, channels, fs, samples, name=None, range=(-10.,10.), dataAcquired=None, dataChunk=100e-3, bufDuration=30, referenced=True, accurateFS=True, timebaseSrc=None, timebaseRate=None, startTrigger=None): ''' Args: channels (str): Example: '/dev1/ai0' or '/dev2/ai0:15' fs (float): Input sampling rate. Depending on the timebase clock, device might not be able to generate the requested rate accurately. samples (int): Number of samples to read from the device. If set to numpy.inf, task will go into infinite samples mode. name (str): Optional name for the task. range (tuple of float): Input voltage range. This adjusts the output DAC for the best quantization resolution possible. dataAcquired (callable): In infinite samples mode, this function is called when a specific number of samples are acquired. dataChunk (float): In infinite samples mode, how long in seconds until the acquired data are read from the device and given to the `dataAcquired` event. bufDuration (float): In infinite samples mode, determines how long should the software buffer be in seconds. The actual buffer size depends on the specified sampling rate. referenced (bool): Referenced (AI GND) vs. non-referenced (AI SENSE) measurement. See: http://www.ni.com/white-paper/3344/en/ zone.ni.com/reference/en-XX/help/370466Y-01/measfunds/refsingleended/ accurateFS (bool): If True, when device is not able to generate the requested sampling frequency accurately, the task will fail and a ValueError will be raised. If False, an inaccurate sampling frequency will only be reported with a warning. timebaseSrc (str): The terminal to use as the timebase for the sample clock. When multiple DAQ devices are connected via an RTSI cable, this value can be used to synchronize their sampling in order to minimize long term offset caused by clock jitter. See the following link for information on terminals: zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/termnames timebaseRate (float): The rate of the specified `timebaseSrc` in Hz. This value is only needed when using an external timebase. startTrigger (str): Configures the task to begin acquisition on rising edge of a digital signal. Note that the task should have already been started for the trigger to work. See the following link for information on trigger sources: zone.ni.com/reference/en-XX/help/370466Y-01/mxcncpts/termnames ''' super().__init__(channels, fs, samples, name) if SIM and samples!=np.inf: raise NotImplementedError('AnalogInput is not yet implemented for ' 'finite samples in `SIM` mode') if not SIM: config = mx.DAQmx_Val_RSE if referenced else mx.DAQmx_Val_NRSE self._task.CreateAIVoltageChan(self.channels, None, config, *range, mx.DAQmx_Val_Volts, None) self._dataAcquired = misc.Event(dataAcquired) self._dataChunk = dataChunk if samples==np.inf: bufSize = int(np.ceil(fs*bufDuration)) if not SIM: self._task.CfgSampClkTiming('', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_ContSamps, 0) self._task.SetBufInputBufSize(bufSize) self._callbackPtr = mx.DAQmxEveryNSamplesEventCallbackPtr( self._callback) self._task.RegisterEveryNSamplesEvent( mx.DAQmx_Val_Acquired_Into_Buffer, int(dataChunk*fs), 0, self._callbackPtr, None) else: bufSize = samples if not SIM: self._task.CfgSampClkTiming('', fs, mx.DAQmx_Val_Rising, mx.DAQmx_Val_FiniteSamps, samples) self._postInit(accurateFS, timebaseSrc, timebaseRate, startTrigger) pypeline.Sampled.__init__(self, fs=self._fs, channels=self._lineCount) if SIM: self._simBuffer = misc.CircularBuffer((self.lineCount, bufSize)) # set simulated acquisition interval self._simInterval = dataChunk