private void analogInCallback_computeGain(IAsyncResult ar) { double[] state = (double[])ar.AsyncState; int ch = (int)state[0]; double f = state[1]; int reader = (int)state[3]; ButterworthBandpassFilter bwfilt = null; if (checkBox_diagnosticsDigitalFilter.Checked) { bwfilt = new ButterworthBandpassFilter(1, spikeSamplingRate, f - f / 8, f + f / 8); } double[,] data = diagnosticsReaders[reader].EndReadMultiSample(ar); double[] oneChannelData = new double[data.GetLength(1)]; double RMSinput = 0.707106704695506 * Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value); if (checkBox_diagnosticsVotlageDivider.Checked) { RMSinput /= Convert.ToDouble(textBox_voltageDivider.Text); } if (ch != -1 && ch < (reader + 1) * 32 && ch >= reader * 32) //If the channel is not "all channels" it should be in the particular device's range //if (ch > 0) { for (int i = 0; i < data.GetLength(1); ++i) { oneChannelData[i] = data[ch - 1, i]; } //Filter data to bring out pure tone if (checkBox_diagnosticsDigitalFilter.Checked && bwfilt != null) { oneChannelData = bwfilt.FilterData(oneChannelData); } double rms = rootMeanSquared(oneChannelData); //DEBUGGING ch = 1; gains[ch - 1][(int)state[2]] = rms / RMSinput; gains[ch - 1][(int)state[2]] = 20 * Math.Log10(gains[ch - 1][(int)state[2]]); } else if (ch == -1) //Do all channels at once, but this requires special hardware (like Plexon headstage tester) { for (int i = 0; i < numChannels; ++i) { if (checkBox_diagnosticsDigitalFilter.Checked) { oneChannelData = bwfilt.FilterData(ArrayOperation.CopyRow(data, i)); } oneChannelData = ArrayOperation.CopyRow(data, i); double rms = rootMeanSquared(oneChannelData); gains[i][(int)state[2]] = rms / RMSinput; gains[i][(int)state[2]] = 20 * Math.Log10(gains[i][(int)state[2]]); } } }
void bgWorker_DoWork(object sender, DoWorkEventArgs e) { //Measure each channel for (int c = 0; c < numChannels && !bgWorker.CancellationPending; ++c) { UInt32 MuxData = StimPulse.channel2MUX(Convert.ToDouble(startChannel + c)); //Setup digital waveform, open MUX channel stimDigitalWriter.WriteSingleSamplePort(true, MuxData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); double numPeriodsUsed = numPeriods; for (int f = 0; f < freqs.GetLength(0) && !bgWorker.CancellationPending; ++f) { //Update progress bars bgWorker.ReportProgress(100 * (f + (c * freqs.Length)) / (numChannels * freqs.Length), new double[] { startChannel + c, freqs[f] }); //Create test wave double numSeconds = 1 / freqs[f]; if (numSeconds * numPeriods < 0.1) numPeriodsUsed = Math.Ceiling(0.1 * freqs[f]); SineSignal testWave = new SineSignal(freqs[f], commandVoltage); //Generate a 100 mV sine wave at 1000 Hz double[] testWaveValues = testWave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round(numSeconds * (double)IMPEDANCE_SAMPLING_RATE)); int size = Convert.ToInt32(numSeconds * IMPEDANCE_SAMPLING_RATE); double[,] analogPulse = new double[4, size]; for (int i = 0; i < size; ++i) analogPulse[0 + 2, i] = testWaveValues[i]; impedanceRecord.Timing.SamplesPerChannel = (long)(numPeriodsUsed * size); stimAnalogTask.Timing.SamplesPerChannel = (long)(numPeriodsUsed * size); //Do numperiods cycles of sine wave //Deliver pulse stimAnalogWriter.WriteMultiSample(true, analogPulse); double[] data = impedanceReader.ReadMultiSample((int)(numPeriodsUsed * size)); #region Calculate Impedance //Remove DC offset double mData = 0.0; for (int i = 0; i < data.Length; ++i) mData += data[i]; mData /= data.Length; for (int i = 0; i < data.Length; ++i) data[i] -= mData; //Filter data with Butterworth, if checked if (useBandpassFilter) { ButterworthBandpassFilter bwfilt = new ButterworthBandpassFilter(1, IMPEDANCE_SAMPLING_RATE, freqs[f] - freqs[f] / 4, freqs[f] + freqs[f] / 4); data = bwfilt.FilterData(data); } //Use matched filter to reduce noise, if checked (slow) if (useMatchedFilter) { SineSignal wave = new SineSignal(freqs[f], 1.0); //Create a sine wave at test frequency of amplitude 1 double[] h; //filter //If data is very long, subsample by an order of magnitude if (data.Length > 1E6) { double[] dataNew = new double[(int)Math.Floor((double)data.Length / 10)]; for (int i = 0; i < dataNew.Length; ++i) dataNew[i] = data[i * 10]; data = dataNew; dataNew = null; h = wave.Generate(IMPEDANCE_SAMPLING_RATE / 10, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / (freqs[f] * 10))); //Generate one period } else { h = wave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / freqs[f])); //Generate one period } wave = null; //Compute filter power double phh = 0.0; for (int i = 0; i < h.Length; ++i) phh += h[i] * h[i]; //Normalize filter so power is 1 for (int i = 0; i < h.Length; ++i) h[i] /= phh; //sw.Start(); double[] x = NationalInstruments.Analysis.Dsp.SignalProcessing.Convolve(data, h); //sw.Stop(); //TimeSpan ts = sw.Elapsed; //System.Diagnostics.Debug.WriteLine("ms = " + ts.Milliseconds + "\t s = " + ts.Seconds + "\t min = " + ts.Minutes); int offset = (int)(h.Length * 0.5); for (int i = 0; i < data.Length; ++i) data[i] = x[i + offset]; //Take center values } double rms = rootMeanSquared(data); if (isCurrentControlled) //Current-controlled { impedance[c][f] = rms / (0.707106704695506 * commandVoltage / RCurr); //Account for 6.8 MOhm resistor in parallel impedance[c][f] = 1.0 / (1.0 / impedance[c][f] - 1.0 / 6800000.0); } else //Voltage-controlled { double gain = 1.0 + (49400.0 / RGain); //Based on LT in-amp impedance[c][f] = (0.707106704695506 * commandVoltage) / ((rms / gain) / RMeas); } #endregion //Wait until recording and stim are finished stimAnalogTask.WaitUntilDone(); impedanceRecord.WaitUntilDone(); stimAnalogTask.Stop(); impedanceRecord.Stop(); } //De-select channel on mux stimDigitalWriter.WriteSingleSamplePort(true, 0); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); //Notify that channel is done if (alertChannelFinished != null) alertChannelFinished(this, c, startChannel + c, impedance, freqs); } //Reset muxes bool[] fData = new bool[Properties.Settings.Default.StimPortBandwidth]; stimDigitalWriter.WriteSingleSampleMultiLine(true, fData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); }
private void analogInCallback_impedance(IAsyncResult ar) { double[] state = (double[])ar.AsyncState; int ch = (int)state[0]; double f = state[1]; double[] data = impedanceReader.EndReadMultiSample(ar); //Remove DC offset double mData = 0.0; for (int i = 0; i < data.Length; ++i) mData += data[i]; mData /= data.Length; for (int i = 0; i < data.Length; ++i) data[i] -= mData; //Filter data with Butterworth, if checked if (useBandpassFilter) { ButterworthBandpassFilter bwfilt = new ButterworthBandpassFilter(1, IMPEDANCE_SAMPLING_RATE, f - f / 4, f + f / 4); data = bwfilt.FilterData(data); } //Use matched filter to reduce noise, if checked (slow) if (useMatchedFilter) { //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); SineSignal wave = new SineSignal(f, 1.0); //Create a sine wave at test frequency of amplitude 1 double[] h; //filter //If data is very long, subsample by an order of magnitude if (data.Length > 1E6) { double[] dataNew = new double[(int)Math.Floor((double)data.Length / 10)]; for (int i = 0; i < dataNew.Length; ++i) dataNew[i] = data[i * 10]; data = dataNew; dataNew = null; h = wave.Generate(IMPEDANCE_SAMPLING_RATE / 10, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / (f * 10))); //Generate one period } else { h = wave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / f)); //Generate one period } wave = null; //GC.Collect(); //this uses a lot of memory //Compute filter power double phh = 0.0; for (int i = 0; i < h.Length; ++i) phh += h[i] * h[i]; //Normalize filter so power is 1 for (int i = 0; i < h.Length; ++i) h[i] /= phh; //sw.Start(); double[] x = NationalInstruments.Analysis.Dsp.SignalProcessing.Convolve(data, h); //sw.Stop(); //TimeSpan ts = sw.Elapsed; //System.Diagnostics.Debug.WriteLine("ms = " + ts.Milliseconds + "\t s = " + ts.Seconds + "\t min = " + ts.Minutes); int offset = (int)(h.Length * 0.5); for (int i = 0; i < data.Length; ++i) data[i] = x[i + offset]; //Take center values } double rms = rootMeanSquared(data); if (Convert.ToBoolean(state[3])) //Current-controlled { impedance[ch][(int)state[2]] = rms / (0.707106704695506 * commandVoltage / RCurr); //Account for 6.8 MOhm resistor in parallel impedance[ch][(int)state[2]] = 1.0 / (1.0 / impedance[ch][(int)state[2]] - 1.0 / 6800000.0); } else //Voltage-controlled { double gain = 1.0 + (49400.0 / RGain); //Based on LT in-amp impedance[ch][(int)state[2]] = (0.707106704695506 * commandVoltage) / ((rms / gain) / RMeas); } }
private void analogInCallback_computeGain(IAsyncResult ar) { double[] state = (double[])ar.AsyncState; int ch = (int)state[0]; double f = state[1]; int reader = (int)state[3]; ButterworthBandpassFilter bwfilt = null; if (checkBox_diagnosticsDigitalFilter.Checked) bwfilt = new ButterworthBandpassFilter(1, spikeSamplingRate, f - f / 8, f + f / 8); double[,] data = diagnosticsReaders[reader].EndReadMultiSample(ar); double[] oneChannelData = new double[data.GetLength(1)]; double RMSinput = 0.707106704695506 * Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value); if (checkBox_diagnosticsVotlageDivider.Checked) RMSinput /= Convert.ToDouble(textBox_voltageDivider.Text); if (ch != -1 && ch < (reader + 1) * 32 && ch >= reader * 32) //If the channel is not "all channels" it should be in the particular device's range //if (ch > 0) { for (int i = 0; i < data.GetLength(1); ++i) oneChannelData[i] = data[ch - 1, i]; //Filter data to bring out pure tone if (checkBox_diagnosticsDigitalFilter.Checked && bwfilt != null) oneChannelData = bwfilt.FilterData(oneChannelData); double rms = rootMeanSquared(oneChannelData); //DEBUGGING ch = 1; gains[ch - 1][(int)state[2]] = rms / RMSinput; gains[ch - 1][(int)state[2]] = 20 * Math.Log10(gains[ch - 1][(int)state[2]]); } else if (ch == -1) //Do all channels at once, but this requires special hardware (like Plexon headstage tester) { for (int i = 0; i < numChannels; ++i) { if (checkBox_diagnosticsDigitalFilter.Checked) oneChannelData = bwfilt.FilterData(ArrayOperation.CopyRow(data, i)); oneChannelData = ArrayOperation.CopyRow(data, i); double rms = rootMeanSquared(oneChannelData); gains[i][(int)state[2]] = rms / RMSinput; gains[i][(int)state[2]] = 20 * Math.Log10(gains[i][(int)state[2]]); } } }
private void analogInCallback_impedance(IAsyncResult ar) { double[] state = (double[])ar.AsyncState; int ch = (int)state[0]; double f = state[1]; double[] data = impedanceReader.EndReadMultiSample(ar); //Remove DC offset double mData = 0.0; for (int i = 0; i < data.Length; ++i) { mData += data[i]; } mData /= data.Length; for (int i = 0; i < data.Length; ++i) { data[i] -= mData; } //Filter data with Butterworth, if checked if (useBandpassFilter) { ButterworthBandpassFilter bwfilt = new ButterworthBandpassFilter(1, IMPEDANCE_SAMPLING_RATE, f - f / 4, f + f / 4); data = bwfilt.FilterData(data); } //Use matched filter to reduce noise, if checked (slow) if (useMatchedFilter) { //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); SineSignal wave = new SineSignal(f, 1.0); //Create a sine wave at test frequency of amplitude 1 double[] h; //filter //If data is very long, subsample by an order of magnitude if (data.Length > 1E6) { double[] dataNew = new double[(int)Math.Floor((double)data.Length / 10)]; for (int i = 0; i < dataNew.Length; ++i) { dataNew[i] = data[i * 10]; } data = dataNew; dataNew = null; h = wave.Generate(IMPEDANCE_SAMPLING_RATE / 10, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / (f * 10))); //Generate one period } else { h = wave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / f)); //Generate one period } wave = null; //GC.Collect(); //this uses a lot of memory //Compute filter power double phh = 0.0; for (int i = 0; i < h.Length; ++i) { phh += h[i] * h[i]; } //Normalize filter so power is 1 for (int i = 0; i < h.Length; ++i) { h[i] /= phh; } //sw.Start(); double[] x = NationalInstruments.Analysis.Dsp.SignalProcessing.Convolve(data, h); //sw.Stop(); //TimeSpan ts = sw.Elapsed; //System.Diagnostics.Debug.WriteLine("ms = " + ts.Milliseconds + "\t s = " + ts.Seconds + "\t min = " + ts.Minutes); int offset = (int)(h.Length * 0.5); for (int i = 0; i < data.Length; ++i) { data[i] = x[i + offset]; //Take center values } } double rms = rootMeanSquared(data); if (Convert.ToBoolean(state[3])) //Current-controlled { impedance[ch][(int)state[2]] = rms / (0.707106704695506 * commandVoltage / RCurr); //Account for 6.8 MOhm resistor in parallel impedance[ch][(int)state[2]] = 1.0 / (1.0 / impedance[ch][(int)state[2]] - 1.0 / 6800000.0); } else //Voltage-controlled { double gain = 1.0 + (49400.0 / RGain); //Based on LT in-amp impedance[ch][(int)state[2]] = (0.707106704695506 * commandVoltage) / ((rms / gain) / RMeas); } }
void bgWorker_DoWork(object sender, DoWorkEventArgs e) { //Measure each channel for (int c = 0; c < numChannels && !bgWorker.CancellationPending; ++c) { UInt32 MuxData = StimPulse.channel2MUX(Convert.ToDouble(startChannel + c)); //Setup digital waveform, open MUX channel stimDigitalWriter.WriteSingleSamplePort(true, MuxData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); double numPeriodsUsed = numPeriods; for (int f = 0; f < freqs.GetLength(0) && !bgWorker.CancellationPending; ++f) { //Update progress bars bgWorker.ReportProgress(100 * (f + (c * freqs.Length)) / (numChannels * freqs.Length), new double[] { startChannel + c, freqs[f] }); //Create test wave double numSeconds = 1 / freqs[f]; if (numSeconds * numPeriods < 0.1) { numPeriodsUsed = Math.Ceiling(0.1 * freqs[f]); } SineSignal testWave = new SineSignal(freqs[f], commandVoltage); //Generate a 100 mV sine wave at 1000 Hz double[] testWaveValues = testWave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round(numSeconds * (double)IMPEDANCE_SAMPLING_RATE)); int size = Convert.ToInt32(numSeconds * IMPEDANCE_SAMPLING_RATE); double[,] analogPulse = new double[4, size]; for (int i = 0; i < size; ++i) { analogPulse[0 + 2, i] = testWaveValues[i]; } impedanceRecord.Timing.SamplesPerChannel = (long)(numPeriodsUsed * size); stimAnalogTask.Timing.SamplesPerChannel = (long)(numPeriodsUsed * size); //Do numperiods cycles of sine wave //Deliver pulse stimAnalogWriter.WriteMultiSample(true, analogPulse); double[] data = impedanceReader.ReadMultiSample((int)(numPeriodsUsed * size)); #region Calculate Impedance //Remove DC offset double mData = 0.0; for (int i = 0; i < data.Length; ++i) { mData += data[i]; } mData /= data.Length; for (int i = 0; i < data.Length; ++i) { data[i] -= mData; } //Filter data with Butterworth, if checked if (useBandpassFilter) { ButterworthBandpassFilter bwfilt = new ButterworthBandpassFilter(1, IMPEDANCE_SAMPLING_RATE, freqs[f] - freqs[f] / 4, freqs[f] + freqs[f] / 4); data = bwfilt.FilterData(data); } //Use matched filter to reduce noise, if checked (slow) if (useMatchedFilter) { SineSignal wave = new SineSignal(freqs[f], 1.0); //Create a sine wave at test frequency of amplitude 1 double[] h; //filter //If data is very long, subsample by an order of magnitude if (data.Length > 1E6) { double[] dataNew = new double[(int)Math.Floor((double)data.Length / 10)]; for (int i = 0; i < dataNew.Length; ++i) { dataNew[i] = data[i * 10]; } data = dataNew; dataNew = null; h = wave.Generate(IMPEDANCE_SAMPLING_RATE / 10, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / (freqs[f] * 10))); //Generate one period } else { h = wave.Generate(IMPEDANCE_SAMPLING_RATE, (long)Math.Round((double)IMPEDANCE_SAMPLING_RATE / freqs[f])); //Generate one period } wave = null; //Compute filter power double phh = 0.0; for (int i = 0; i < h.Length; ++i) { phh += h[i] * h[i]; } //Normalize filter so power is 1 for (int i = 0; i < h.Length; ++i) { h[i] /= phh; } //sw.Start(); double[] x = NationalInstruments.Analysis.Dsp.SignalProcessing.Convolve(data, h); //sw.Stop(); //TimeSpan ts = sw.Elapsed; //System.Diagnostics.Debug.WriteLine("ms = " + ts.Milliseconds + "\t s = " + ts.Seconds + "\t min = " + ts.Minutes); int offset = (int)(h.Length * 0.5); for (int i = 0; i < data.Length; ++i) { data[i] = x[i + offset]; //Take center values } } double rms = rootMeanSquared(data); if (isCurrentControlled) //Current-controlled { impedance[c][f] = rms / (0.707106704695506 * commandVoltage / RCurr); //Account for 6.8 MOhm resistor in parallel impedance[c][f] = 1.0 / (1.0 / impedance[c][f] - 1.0 / 6800000.0); } else //Voltage-controlled { double gain = 1.0 + (49400.0 / RGain); //Based on LT in-amp impedance[c][f] = (0.707106704695506 * commandVoltage) / ((rms / gain) / RMeas); } #endregion //Wait until recording and stim are finished stimAnalogTask.WaitUntilDone(); impedanceRecord.WaitUntilDone(); stimAnalogTask.Stop(); impedanceRecord.Stop(); } //De-select channel on mux stimDigitalWriter.WriteSingleSamplePort(true, 0); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); //Notify that channel is done if (alertChannelFinished != null) { alertChannelFinished(this, c, startChannel + c, impedance, freqs); } } //Reset muxes bool[] fData = new bool[Properties.Settings.Default.StimPortBandwidth]; stimDigitalWriter.WriteSingleSampleMultiLine(true, fData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); }