private void sine_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            SineSignal sineSignal = sender as SineSignal;

            sineSignal.Update();
            if (!suppressSourceUpdate)
            {
                updateSource();
            }
        }
Beispiel #2
0
        private double[] AcquireData(double frequency, double amplitude, double phase, double numberSamples, double noiseAmplitude)
        {
            // Test using signal generation
            SineSignal       sineSignal = new SineSignal(frequency, amplitude, phase);
            WhiteNoiseSignal noise      = new WhiteNoiseSignal(noiseAmplitude);
            SignalGenerator  generator  = new SignalGenerator(numberSamples, (long)numberSamples);

            generator.Signals.Add(sineSignal);
            generator.Signals.Add(noise);
            return(generator.Generate());
        }
        private void btnAddSine_Click(object sender, RoutedEventArgs e)
        {
            SineSignal signal = new SineSignal();

            if (sources.Count > 0)
            {
                signal.SetSampleRate(sources[0].SampleRate);
                signal.SetNumberOfSamples(sources[0].NumberOfSamples);
            }
            else
            {
                GlobalSampleRate = signal.SampleRate;
            }
            signal.Update();

            sources.Add(signal);
            signal.PropertyChanged += new PropertyChangedEventHandler(sine_PropertyChanged);
            signal.PropertyChanged += new PropertyChangedEventHandler(signal_PropertyChanged);

            sourcesList.SelectedIndex = sources.IndexOf(signal);

            updateSource();
        }
        private double[] CreateSignal()
        {
            //Try catch untuk semua parameter yang akan digunakan (freq,amp,phase,sampleSize,samplingRate)
            double[] signal = new double[sampleSize];
            switch (signalType)
            {
                case "Sine":
                    SineSignal _sineSignal = new SineSignal(frequency, amplitude, phase);
                    signal = _sineSignal.Generate(samplingRate, sampleSize);
                    break;
                case "Noise":
                    WhiteNoiseSignal _whiteNoise = new WhiteNoiseSignal(amplitude, DateTime.Now.Second);
                    signal = _whiteNoise.Generate(samplingRate, sampleSize);
                    break;
                case "Square":
                    SquareSignal _squareSignal = new SquareSignal(frequency, amplitude, phase, dutyCycle);
                    signal = _squareSignal.Generate(samplingRate, sampleSize);
                    break;
                case "Saw":
                    SawtoothSignal _sawSignal = new SawtoothSignal(frequency, amplitude, phase);
                    signal = _sawSignal.Generate(samplingRate, sampleSize);
                    break;
            }

            //SignalGenerator generator = new SignalGenerator(
            SignalData = signal;
            return signal;
        }
Beispiel #5
0
        private void button_computeGain_Click(object sender, EventArgs e)
        {
            double startFreq  = Convert.ToDouble(numericUpDown_startFreq.Value);
            double stopFreq   = Convert.ToDouble(numericUpDown_stopFreq.Value);
            double numPeriods = Convert.ToDouble(numericUpDown_numPeriods.Value);

            double[] freqs = new double[1 + Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(Convert.ToDouble(textBox_diagnosticsMult.Text))))]; //This determines the number of frequencies counting by doublings

            radioButton_stimVoltageControlled.Checked = true;
            radioButton_stimVoltageControlled_Click(null, null);

            //Populate freqs vector
            freqs[0] = startFreq;
            for (int i = 1; i < freqs.GetLength(0); ++i)
            {
                freqs[i] = freqs[i - 1] * Convert.ToDouble(textBox_diagnosticsMult.Text);
            }

            spikeSamplingRate          = Properties.Settings.Default.RawSampleFrequency;
            buttonStart.Enabled        = false; //So users can't try to get data from the same card
            button_computeGain.Enabled = false;
            button_computeGain.Refresh();
            buttonStart.Refresh();
            spikeTask          = new List <Task>(Properties.Settings.Default.AnalogInDevice.Count);
            diagnosticsReaders = new List <AnalogMultiChannelReader>(Properties.Settings.Default.AnalogInDevice.Count);
            for (int i = 0; i < Properties.Settings.Default.AnalogInDevice.Count; ++i)
            {
                spikeTask.Add(new Task("spikeTask_Diagnostics_" + i));
                int numChannelsPerDevice = (numChannels < 32 ? numChannels : 32);
                for (int j = 0; j < numChannelsPerDevice; ++j)
                {
                    spikeTask[i].AIChannels.CreateVoltageChannel(Properties.Settings.Default.AnalogInDevice[0] + "/ai" + j.ToString(), "",
                                                                 AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts);
                }

                //Change gain based on comboBox values (1-100)
                setGain(spikeTask[i], Properties.Settings.Default.A2Dgain);

                //Verify the Task
                spikeTask[i].Control(TaskAction.Verify);

                spikeTask[i].Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising,
                                                         SampleQuantityMode.FiniteSamples);
                diagnosticsReaders.Add(new AnalogMultiChannelReader(spikeTask[i].Stream));
            }

            spikeTask[0].Timing.ReferenceClockSource = "OnboardClock";
            for (int i = 1; i < spikeTask.Count; ++i)
            {
                spikeTask[i].Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource;
                spikeTask[i].Timing.ReferenceClockRate   = spikeTask[0].Timing.ReferenceClockRate;
            }
            stimPulseTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource;
            stimPulseTask.Timing.ReferenceClockRate   = spikeTask[0].Timing.ReferenceClockRate;

            stimDigitalTask.Dispose();
            stimDigitalTask = new Task("stimDigitalTask");
            if (Properties.Settings.Default.StimPortBandwidth == 32)
            {
                stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "",
                                                         ChannelLineGrouping.OneChannelForAllLines); //To control MUXes
            }
            else if (Properties.Settings.Default.StimPortBandwidth == 8)
            {
                stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "",
                                                         ChannelLineGrouping.OneChannelForAllLines); //To control MUXes
            }
            stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream);
            stimPulseTask.Timing.ConfigureSampleClock("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/SampleClock",
                                                      spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples);
            stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" +
                                                                            Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger",
                                                                            DigitalEdgeStartTriggerEdge.Rising);

            stimDigitalTask.Control(TaskAction.Verify);
            stimPulseTask.Control(TaskAction.Verify);

            switch (Properties.Settings.Default.NumChannels)
            {
            case 0:
                numChannels = 16;
                break;

            case 1:
                numChannels = 32;
                break;

            case 2:
                numChannels = 48;
                break;

            case 3:
                numChannels = 64;
                break;
            }
            //gains = new double[numChannels, freqs.GetLength(0)];
            //numChannels = 1;

            gains = new double[numChannels][];
            for (int i = 0; i < numChannels; ++i)
            {
                gains[i] = new double[freqs.GetLength(0)];
            }
            scatterGraph_diagnostics.ClearData();
            scatterGraph_diagnostics.Plots.Clear();

            textBox_diagnosticsResults.Clear();

            if (!checkBox_diagnosticsBulk.Checked)
            {
                //for (int c = 1; c <= numChannels; ++c)
                for (int c = 13; c < 14; ++c)
                {
                    textBox_diagnosticsResults.Text += "Channel " + c.ToString() + "\r\n\tFrequency (Hz)\tGain (dB)\r\n";

                    scatterGraph_diagnostics.Plots.Add(new ScatterPlot());

                    UInt32 data = StimPulse.channel2MUX((double)c); //Get data bits lined up to control MUXes

                    //Setup digital waveform
                    stimDigitalWriter.WriteSingleSamplePort(true, data);
                    stimDigitalTask.WaitUntilDone();
                    stimDigitalTask.Stop();

                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        double numSeconds = 1 / freqs[f];
                        if (numSeconds * numPeriods < 0.1)
                        {
                            numPeriods = Math.Ceiling(0.1 * freqs[f]);
                        }

                        int        size           = Convert.ToInt32(numSeconds * spikeSamplingRate);
                        SineSignal testWave       = new SineSignal(freqs[f], Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value)); //Generate a 100 mV sine wave at 1000 Hz
                        double[]   testWaveValues = testWave.Generate(spikeSamplingRate, size);

                        double[,] analogPulse = new double[2, size];

                        for (int i = 0; i < size; ++i)
                        {
                            analogPulse[0, i] = testWaveValues[i];
                        }

                        for (int i = 0; i < spikeTask.Count; ++i)
                        {
                            spikeTask[i].Timing.SamplesPerChannel = (long)(numPeriods * size);
                        }

                        stimPulseTask.Timing.SamplesPerChannel = (long)(numPeriods * size); //Do numperiods cycles of sine wave
                        stimPulseWriter.WriteMultiSample(true, analogPulse);

                        double[] stateData = new double[4];
                        stateData[0] = (double)c;
                        stateData[1] = freqs[f];
                        stateData[2] = (double)f;
                        for (int i = diagnosticsReaders.Count - 1; i >= 0; --i)
                        {
                            stateData[3] = (double)i;
                            diagnosticsReaders[i].BeginReadMultiSample((int)(numPeriods * size), analogInCallback_computeGain, (Object)stateData); //Get 5 seconds of "noise"
                        }

                        stimPulseTask.WaitUntilDone();
                        for (int i = 0; i < spikeTask.Count; ++i)
                        {
                            spikeTask[i].WaitUntilDone();
                            spikeTask[i].Stop();
                        }
                        stimPulseTask.Stop();
                    }
                    stimDigitalWriter.WriteSingleSamplePort(true, 0);
                    stimDigitalTask.WaitUntilDone();
                    stimDigitalTask.Stop();
                    //DEBUGGING
                    c = 1;
                    scatterGraph_diagnostics.Plots[c - 1].PlotXY(freqs, gains[c - 1]);
                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        textBox_diagnosticsResults.Text += "\t" + freqs[f].ToString() + "\t" + gains[c - 1][f] + "\r\n";
                    }
                    textBox_diagnosticsResults.Text += "\r\n";
                    scatterGraph_diagnostics.Refresh();

                    //DEBUGGING
                    c = 100;
                }
            }
            else
            {
                for (int f = 0; f < freqs.GetLength(0); ++f)
                {
                    double numSeconds = 1 / freqs[f];
                    if (numSeconds * numPeriods < 0.1)
                    {
                        numPeriods = Math.Ceiling(0.1 * freqs[f]);
                    }

                    int        size           = Convert.ToInt32(numSeconds * spikeSamplingRate);
                    SineSignal testWave       = new SineSignal(freqs[f], Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value)); //Generate a 100 mV sine wave at 1000 Hz
                    double[]   testWaveValues = testWave.Generate(spikeSamplingRate, size);


                    double[,] analogPulse = new double[2, size];

                    for (int i = 0; i < size; ++i)
                    {
                        analogPulse[0, i] = testWaveValues[i];
                    }

                    for (int i = 0; i < spikeTask.Count; ++i)
                    {
                        spikeTask[i].Timing.SamplesPerChannel = (long)(numPeriods * size);
                    }

                    stimPulseTask.Timing.SamplesPerChannel = (long)(numPeriods * size); //Do numperiods cycles of sine wave
                    stimPulseWriter.WriteMultiSample(true, analogPulse);

                    double[] stateData = new double[4];
                    stateData[0] = -1.0;
                    stateData[1] = freqs[f];
                    stateData[2] = (double)f; //Frequency of interest

                    for (int i = diagnosticsReaders.Count - 1; i >= 0; --i)
                    {
                        stateData[3] = (double)i;                                                                                              //Keeps track of which device called the reader
                        diagnosticsReaders[i].BeginReadMultiSample((int)(numPeriods * size), analogInCallback_computeGain, (Object)stateData); //Get 5 seconds of "noise"
                    }

                    stimPulseTask.WaitUntilDone();
                    for (int i = 0; i < spikeTask.Count; ++i)
                    {
                        spikeTask[i].WaitUntilDone();
                        spikeTask[i].Stop();
                    }
                    stimPulseTask.Stop();
                }
                for (int c = 0; c < numChannels; ++c)
                {
                    scatterGraph_diagnostics.Plots.Add(new ScatterPlot());
                    scatterGraph_diagnostics.Plots[c].PlotXY(freqs, gains[c]);
                    textBox_diagnosticsResults.Text += "Channel " + (c + 1).ToString() + "\r\n\tFrequency (Hz)\tGain (dB)\r\n";
                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        textBox_diagnosticsResults.Text += "\t" + freqs[f].ToString() + "\t" + gains[c][f].ToString() + "\r\n";
                    }
                    textBox_diagnosticsResults.Text += "\r\n";
                }
                scatterGraph_diagnostics.Refresh();
            }
            buttonStart.Enabled        = true;
            button_computeGain.Enabled = true;

            //Now, destroy the objects we made
            updateSettings();
            gains = null;
            diagnosticsReaders = null;
        }
        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 button_computeGain_Click(object sender, EventArgs e)
        {
            double startFreq = Convert.ToDouble(numericUpDown_startFreq.Value);
            double stopFreq = Convert.ToDouble(numericUpDown_stopFreq.Value);
            double numPeriods = Convert.ToDouble(numericUpDown_numPeriods.Value);
            double[] freqs = new double[1 + Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(Convert.ToDouble(textBox_diagnosticsMult.Text))))]; //This determines the number of frequencies counting by doublings

            radioButton_stimVoltageControlled.Checked = true;
            radioButton_stimVoltageControlled_Click(null, null);

            //Populate freqs vector
            freqs[0] = startFreq;
            for (int i = 1; i < freqs.GetLength(0); ++i)
                freqs[i] = freqs[i - 1] * Convert.ToDouble(textBox_diagnosticsMult.Text);

            spikeSamplingRate = Properties.Settings.Default.RawSampleFrequency;
            buttonStart.Enabled = false;  //So users can't try to get data from the same card
            button_computeGain.Enabled = false;
            button_computeGain.Refresh();
            buttonStart.Refresh();
            spikeTask = new List<Task>(Properties.Settings.Default.AnalogInDevice.Count);
            diagnosticsReaders = new List<AnalogMultiChannelReader>(Properties.Settings.Default.AnalogInDevice.Count);
            for (int i = 0; i < Properties.Settings.Default.AnalogInDevice.Count; ++i)
            {
                spikeTask.Add(new Task("spikeTask_Diagnostics_" + i));
                int numChannelsPerDevice = (numChannels < 32 ? numChannels : 32);
                for (int j = 0; j < numChannelsPerDevice; ++j)
                    spikeTask[i].AIChannels.CreateVoltageChannel(Properties.Settings.Default.AnalogInDevice[0] + "/ai" + j.ToString(), "",
                        AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts);

                //Change gain based on comboBox values (1-100)
                setGain(spikeTask[i], Properties.Settings.Default.A2Dgain);

                //Verify the Task
                spikeTask[i].Control(TaskAction.Verify);

                spikeTask[i].Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising,
                    SampleQuantityMode.FiniteSamples);
                diagnosticsReaders.Add(new AnalogMultiChannelReader(spikeTask[i].Stream));
            }

            spikeTask[0].Timing.ReferenceClockSource = "OnboardClock";
            for (int i = 1; i < spikeTask.Count; ++i)
            {
                spikeTask[i].Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource;
                spikeTask[i].Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate;
            }
            stimPulseTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource;
            stimPulseTask.Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate;

            stimDigitalTask.Dispose();
            stimDigitalTask = new Task("stimDigitalTask");
            if (Properties.Settings.Default.StimPortBandwidth == 32)
                stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "",
                    ChannelLineGrouping.OneChannelForAllLines); //To control MUXes
            else if (Properties.Settings.Default.StimPortBandwidth == 8)
                stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "",
                    ChannelLineGrouping.OneChannelForAllLines); //To control MUXes
            stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream);
            stimPulseTask.Timing.ConfigureSampleClock("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/SampleClock",
                spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples);
            stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" +
                                Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger",
                                DigitalEdgeStartTriggerEdge.Rising);

            stimDigitalTask.Control(TaskAction.Verify);
            stimPulseTask.Control(TaskAction.Verify);

            switch (Properties.Settings.Default.NumChannels)
            {
                case 0:
                    numChannels = 16;
                    break;
                case 1:
                    numChannels = 32;
                    break;
                case 2:
                    numChannels = 48;
                    break;
                case 3:
                    numChannels = 64;
                    break;
            }
            //gains = new double[numChannels, freqs.GetLength(0)];
            //numChannels = 1;

            gains = new double[numChannels][];
            for (int i = 0; i < numChannels; ++i)
                gains[i] = new double[freqs.GetLength(0)];
            scatterGraph_diagnostics.ClearData();
            scatterGraph_diagnostics.Plots.Clear();

            textBox_diagnosticsResults.Clear();

            if (!checkBox_diagnosticsBulk.Checked)
            {
                //for (int c = 1; c <= numChannels; ++c)
                for (int c = 13; c < 14; ++c)
                {
                    textBox_diagnosticsResults.Text += "Channel " + c.ToString() + "\r\n\tFrequency (Hz)\tGain (dB)\r\n";

                    scatterGraph_diagnostics.Plots.Add(new ScatterPlot());

                    UInt32 data = StimPulse.channel2MUX((double)c); //Get data bits lined up to control MUXes

                    //Setup digital waveform
                    stimDigitalWriter.WriteSingleSamplePort(true, data);
                    stimDigitalTask.WaitUntilDone();
                    stimDigitalTask.Stop();

                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        double numSeconds = 1 / freqs[f];
                        if (numSeconds * numPeriods < 0.1)
                        {
                            numPeriods = Math.Ceiling(0.1 * freqs[f]);
                        }

                        int size = Convert.ToInt32(numSeconds * spikeSamplingRate);
                        SineSignal testWave = new SineSignal(freqs[f], Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value));  //Generate a 100 mV sine wave at 1000 Hz
                        double[] testWaveValues = testWave.Generate(spikeSamplingRate, size);

                        double[,] analogPulse = new double[2, size];

                        for (int i = 0; i < size; ++i)
                            analogPulse[0, i] = testWaveValues[i];

                        for (int i = 0; i < spikeTask.Count; ++i)
                            spikeTask[i].Timing.SamplesPerChannel = (long)(numPeriods * size);

                        stimPulseTask.Timing.SamplesPerChannel = (long)(numPeriods * size); //Do numperiods cycles of sine wave
                        stimPulseWriter.WriteMultiSample(true, analogPulse);

                        double[] stateData = new double[4];
                        stateData[0] = (double)c;
                        stateData[1] = freqs[f];
                        stateData[2] = (double)f;
                        for (int i = diagnosticsReaders.Count - 1; i >= 0; --i)
                        {
                            stateData[3] = (double)i;
                            diagnosticsReaders[i].BeginReadMultiSample((int)(numPeriods * size), analogInCallback_computeGain, (Object)stateData); //Get 5 seconds of "noise"
                        }

                        stimPulseTask.WaitUntilDone();
                        for (int i = 0; i < spikeTask.Count; ++i)
                        {
                            spikeTask[i].WaitUntilDone();
                            spikeTask[i].Stop();
                        }
                        stimPulseTask.Stop();
                    }
                    stimDigitalWriter.WriteSingleSamplePort(true, 0);
                    stimDigitalTask.WaitUntilDone();
                    stimDigitalTask.Stop();
                    //DEBUGGING
                    c = 1;
                    scatterGraph_diagnostics.Plots[c - 1].PlotXY(freqs, gains[c - 1]);
                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        textBox_diagnosticsResults.Text += "\t" + freqs[f].ToString() + "\t" + gains[c - 1][f] + "\r\n";
                    }
                    textBox_diagnosticsResults.Text += "\r\n";
                    scatterGraph_diagnostics.Refresh();

                    //DEBUGGING
                    c = 100;
                }
            }
            else
            {
                for (int f = 0; f < freqs.GetLength(0); ++f)
                {
                    double numSeconds = 1 / freqs[f];
                    if (numSeconds * numPeriods < 0.1)
                    {
                        numPeriods = Math.Ceiling(0.1 * freqs[f]);
                    }

                    int size = Convert.ToInt32(numSeconds * spikeSamplingRate);
                    SineSignal testWave = new SineSignal(freqs[f], Convert.ToDouble(numericUpDown_diagnosticsVoltage.Value));  //Generate a 100 mV sine wave at 1000 Hz
                    double[] testWaveValues = testWave.Generate(spikeSamplingRate, size);

                    double[,] analogPulse = new double[2, size];

                    for (int i = 0; i < size; ++i)
                        analogPulse[0, i] = testWaveValues[i];

                    for (int i = 0; i < spikeTask.Count; ++i)
                        spikeTask[i].Timing.SamplesPerChannel = (long)(numPeriods * size);

                    stimPulseTask.Timing.SamplesPerChannel = (long)(numPeriods * size); //Do numperiods cycles of sine wave
                    stimPulseWriter.WriteMultiSample(true, analogPulse);

                    double[] stateData = new double[4];
                    stateData[0] = -1.0;
                    stateData[1] = freqs[f];
                    stateData[2] = (double)f; //Frequency of interest

                    for (int i = diagnosticsReaders.Count - 1; i >= 0; --i)
                    {
                        stateData[3] = (double)i; //Keeps track of which device called the reader
                        diagnosticsReaders[i].BeginReadMultiSample((int)(numPeriods * size), analogInCallback_computeGain, (Object)stateData); //Get 5 seconds of "noise"
                    }

                    stimPulseTask.WaitUntilDone();
                    for (int i = 0; i < spikeTask.Count; ++i)
                    {
                        spikeTask[i].WaitUntilDone();
                        spikeTask[i].Stop();
                    }
                    stimPulseTask.Stop();
                }
                for (int c = 0; c < numChannels; ++c)
                {
                    scatterGraph_diagnostics.Plots.Add(new ScatterPlot());
                    scatterGraph_diagnostics.Plots[c].PlotXY(freqs, gains[c]);
                    textBox_diagnosticsResults.Text += "Channel " + (c + 1).ToString() + "\r\n\tFrequency (Hz)\tGain (dB)\r\n";
                    for (int f = 0; f < freqs.GetLength(0); ++f)
                    {
                        textBox_diagnosticsResults.Text += "\t" + freqs[f].ToString() + "\t" + gains[c][f].ToString() + "\r\n";
                    }
                    textBox_diagnosticsResults.Text += "\r\n";
                }
                scatterGraph_diagnostics.Refresh();
            }
            buttonStart.Enabled = true;
            button_computeGain.Enabled = true;

            //Now, destroy the objects we made
            updateSettings();
            gains = null;
            diagnosticsReaders = null;
        }
Beispiel #9
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);
            }
        }
Beispiel #10
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();
        }