Example #1
0
        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]]);
                }
            }
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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();
        }