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]]); } } }
// Train the SALPA filter private void button_Train_Click(object sender, EventArgs e) { thrSALPA = new rawType[Properties.Settings.Default.NumChannels]; this.Cursor = Cursors.WaitCursor; label_noise.Text = "Noise levels not trained."; label_noise.ForeColor = Color.Red; label_noise.Update(); buttonStart.Enabled = false; //So users can't try to get data from the same card int numChannelsPerDevice = (numChannels > 32 ? 32 : numChannels); int numDevices = (numChannels > 32 ? Properties.Settings.Default.AnalogInDevice.Count : 1); spikeTask = new List <Task>(numDevices); for (int i = 0; i < numDevices; ++i) { spikeTask.Add(new Task("SALPATrainingTask_" + i)); for (int j = 0; j < numChannelsPerDevice; ++j) { spikeTask[i].AIChannels.CreateVoltageChannel(Properties.Settings.Default.AnalogInDevice[i] + "/ai" + j.ToString(), "", AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts); } } //Change gain based on comboBox values (1-100) for (int i = 0; i < spikeTask.Count; ++i) { setGain(spikeTask[i], Properties.Settings.Default.A2Dgain); } for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Timing.ReferenceClockSource = "OnboardClock"; } for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(spikeSamplingRate / 2)); } // Set reference clock source for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Timing.ReferenceClockSource = "OnboardClock"; } //Verify the Task for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Control(TaskAction.Verify); } List <AnalogMultiChannelReader> readers = new List <AnalogMultiChannelReader>(spikeTask.Count); for (int i = 0; i < spikeTask.Count; ++i) { readers.Add(new AnalogMultiChannelReader(spikeTask[i].Stream)); } double[][] data = new double[numChannels][]; int c = 0; //Last channel of 'data' written to for (int i = 0; i < readers.Count; ++i) { double[,] tempData = readers[i].ReadMultiSample((int)(NUM_SECONDS_TRAINING * spikeSamplingRate)); //Get a few seconds of "noise" for (int j = 0; j < tempData.GetLength(0); ++j) { data[c++] = ArrayOperation.CopyRow(tempData, j); } } for (int i = 0; i < numChannels; ++i) { thrSALPA[i] = 9 * (rawType)Statistics.Variance(data[i]) / Math.Pow(Properties.Settings.Default.PreAmpGain, 2); Console.Out.WriteLine("channel " + i + ": thr = " + thrSALPA[i]); } //Now, destroy the objects we made for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Dispose(); } spikeTask.Clear(); spikeTask = null; buttonStart.Enabled = true; label_noise.Text = "Noise levels trained."; label_noise.ForeColor = Color.Green; checkBox_SALPA.Enabled = true; this.Cursor = Cursors.Default; }