private void waveformPlotData_dataAcquired(object sender) { EventPlotData pd = (EventPlotData)sender; if (spkWfmGraph.Visible && !checkBox_freeze.Checked) { int maxWaveforms = pd.MaxWaveforms; List <PlotSpikeWaveform> wfms = pd.read(); for (int i = 0; i < wfms.Count; ++i) { // What channel are we on int channel = wfms[i].channel; // Correct channel mappings if (Properties.Settings.Default.ChannelMapping == "invitro") { channel = (MEAChannelMappings.ch2rcPreMapped[channel, 0] - 1) * 8 + MEAChannelMappings.ch2rcPreMapped[channel, 1] - 1; } // Plot the spikes if (wfms[i].unit == null) { spkWfmGraph.plotY(wfms[i].waveform, pd.horizontalOffset(channel), 1, NRSnipBrainbow, channel, numSpkWfms[channel]++ + channel * maxWaveforms); } else { spkWfmGraph.plotY(wfms[i].waveform, pd.horizontalOffset(channel), 1, NRUnitBrainbow[(int)wfms[i].unit], channel, numSpkWfms[channel]++ + channel * maxWaveforms); } // Tally number of waveforms being displayed for each channel numSpkWfms[channel] %= maxWaveforms; } spkWfmGraph.Invalidate(); } else { pd.skipRead(); } }
// Method to set up the recording side of neurorighter private bool NRAcquisitionSetup() { lock (this) { if (!taskRunning) { try { this.Cursor = Cursors.WaitCursor; if (switch_record.Value) { // Create file name if (filenameBase == null) //user hasn't specified a file button_BrowseOutputFile_Click(null, null); //call file selection routine if (filenameBase == null) //this happens if the user pressed cancel for the dialog { MessageBox.Show("An output file must be selected before recording."); //display an error message this.Cursor = Cursors.Default; return true; } // If the user is just doing repeated recordings if (checkbox_repeatRecord.Checked || Properties.Settings.Default.useFidTimeStamp) { DateTime nowDate = DateTime.Now;//Get current time (local to computer); string datePrefix = nowDate.ToString("'-'yyyy'-'MM'-'dd'-'HH'-'mm'-'ss"); filenameBase = originalNameBase + datePrefix; } // Look for old files with same name string[] matchFiles; try { matchFiles = Directory.GetFiles(currentSaveDir, currentSaveFile + "*"); } catch { matchFiles = new string[0]; } if (matchFiles.Length > 0) { DialogResult dr = MessageBox.Show("File " + filenameBase + " exists. Overwrite?", "NeuroRighter Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning); if (dr == DialogResult.No) button_BrowseOutputFile_Click(null, null); //call file selection routine else if (dr == DialogResult.Cancel) { this.Cursor = Cursors.Default; return true; } } // Set file base name + number of channels recordingSettings.SetFID(filenameBase); recordingSettings.SetNumElectrodes(numChannels); } // Find out how many devs and channels/dev we are going to need int numDevices = (numChannels > 32 ? Properties.Settings.Default.AnalogInDevice.Count : 1); numChannelsPerDev = (numChannels < 32 ? numChannels : 32); // Set spike buffer lengths spikeBufferLength = Convert.ToInt32(Properties.Settings.Default.ADCPollingPeriodSec * Properties.Settings.Default.RawSampleFrequency); lfpBufferLength = Convert.ToInt32(Properties.Settings.Default.ADCPollingPeriodSec * Properties.Settings.Default.LFPSampleFrequency); // Create spike aquisition task list spikeTask = new List<Task>(numDevices); Properties.Settings.Default.numSpikeTasks = numDevices; NRAIChannelCollection spikeAqSet = new NRAIChannelCollection(numDevices, numChannelsPerDev); spikeAqSet.SetupSpikeCollection(ref spikeTask); // Check audio and video properties if (Properties.Settings.Default.UseSingleChannelPlayback) spikeOutTask = new Task("spikeOutTask"); //For audio output if (checkBox_video.Checked) //NB: This can't be checked unless video is enabled (no need to check properties) triggerTask = new Task("triggerTask"); // Set MUA sample rate double muaSamplingRate = spikeSamplingRate / MUA_DOWNSAMPLE_FACTOR; //Add LFP channels, if configured if (Properties.Settings.Default.SeparateLFPBoard && Properties.Settings.Default.UseLFPs) { lfpTask = new Task("lfpTask"); for (int i = 0; i < Properties.Settings.Default.NumChannels; ++i) lfpTask.AIChannels.CreateVoltageChannel(Properties.Settings.Default.LFPDevice + "/ai" + i.ToString(), "", AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts); setGain(lfpTask, Properties.Settings.Default.LFPgain); lfpTask.Control(TaskAction.Verify); } //Add EEG channels, if configured if (Properties.Settings.Default.UseEEG) { eegTask = new Task("eegTask"); for (int i = 0; i < Properties.Settings.Default.EEGNumChannels; ++i) eegTask.AIChannels.CreateVoltageChannel(Properties.Settings.Default.EEGDevice + "/ai" + (i).ToString(), "", AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts); setGain(eegTask, (double)Properties.Settings.Default.EEGGain); eegTask.Control(TaskAction.Verify); eegSamplingRate = Properties.Settings.Default.EEGSamplingRate; } //Add channel to control Cineplex, if configured if (checkBox_video.Checked) triggerTask.DOChannels.CreateChannel(Properties.Settings.Default.CineplexDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //Change gain based on comboBox values (1-100) for (int i = 0; i < spikeTask.Count; ++i) setGain(spikeTask[i], Properties.Settings.Default.A2Dgain); //Verify the Tasks for (int i = 0; i < spikeTask.Count; ++i) spikeTask[i].Control(TaskAction.Verify); //if (Properties.Settings.Default.UseSingleChannelPlayback) // spikeOutTask.Control(TaskAction.Verify); //Get sampling rates, set to private variables spikeSamplingRate = Properties.Settings.Default.RawSampleFrequency; lfpSamplingRate = Properties.Settings.Default.LFPSampleFrequency; //Version with videoTask as master clock if (Properties.Settings.Default.UseCineplex) { for (int i = 0; i < spikeTask.Count; ++i) { spikeTask[i].Timing.ReferenceClockSource = videoTask.Timing.ReferenceClockSource; spikeTask[i].Timing.ReferenceClockRate = videoTask.Timing.ReferenceClockRate; } } else { string masterclock = "/" + Properties.Settings.Default.AnalogInDevice[0].ToString() + "/10MhzRefClock";//"OnboardClock";// if (!Properties.Settings.Default.UseStimulator) { //Deal with non M-series devices (these can't use "ReferenceClockSource" Device analogInDevice = DaqSystem.Local.LoadDevice(Properties.Settings.Default.AnalogInDevice[0]); if (analogInDevice.ProductCategory == ProductCategory.MSeriesDaq || analogInDevice.ProductCategory == ProductCategory.XSeriesDaq) spikeTask[0].Timing.ReferenceClockSource = masterclock; //This will be the master clock } else { spikeTask[0].Timing.ReferenceClockSource = masterclock;//stimPulseTask.Timing.ReferenceClockSource; spikeTask[0].Timing.ReferenceClockRate = 10000000.0; //stimPulseTask.Timing.ReferenceClockRate; } for (int i = 1; i < spikeTask.Count; ++i) //Set other analog in tasks to master clock { spikeTask[i].Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource; spikeTask[i].Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate; } } spikeTask[0].Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.RawSampleFrequency / 2)); for (int i = 1; i < spikeTask.Count; ++i) { //Pipe ai dev0's sample clock to slave devices spikeTask[i].Timing.ConfigureSampleClock("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/SampleClock", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.RawSampleFrequency / 2)); //Trigger off of ai dev0's trigger spikeTask[i].Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); // Manually allocate buffer memory //spikeTask[i].Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; } if (Properties.Settings.Default.SeparateLFPBoard && Properties.Settings.Default.UseLFPs) { lfpTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource; lfpTask.Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate; lfpTask.Timing.ConfigureSampleClock("", lfpSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.LFPSampleFrequency / 2)); // Manually allocate buffer memory //lfpTask.Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; } else { Properties.Settings.Default.numLFPTasks = Properties.Settings.Default.numSpikeTasks; } if (Properties.Settings.Default.UseEEG) { eegTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource; eegTask.Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate; eegTask.Timing.ConfigureSampleClock("", eegSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Convert.ToDouble(Properties.Settings.Default.EEGSamplingRate) / 2)); // Manually allocate buffer memory //eegTask.Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; } if (Properties.Settings.Default.UseCineplex) { if (checkBox_video.Checked) { triggerTask.Timing.ConfigureSampleClock("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/SampleClock", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, 3); } if (Properties.Settings.Default.SeparateLFPBoard && Properties.Settings.Default.UseLFPs) { lfpTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); } if (Properties.Settings.Default.UseEEG) { eegTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); } } if (Properties.Settings.Default.UseStimulator && Properties.Settings.Default.RecordStimTimes) { try { numStimReads = new List<int>(numDevices); for (int i = 0; i < spikeTask.Count; ++i) numStimReads.Add(0); stimTimeTask = new Task("stimTimeTask"); stimTimeTask.AIChannels.CreateVoltageChannel(Properties.Settings.Default.StimInfoDevice + "/ai16", "", AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts); stimTimeTask.AIChannels.CreateVoltageChannel(Properties.Settings.Default.StimInfoDevice + "/ai0", "", AITerminalConfiguration.Nrse, -10.0, 10.0, AIVoltageUnits.Volts); //For triggers // Pipe the spikeTasks sample clock to PFI14 on the stim board DaqSystem.Local.ConnectTerminals(spikeTask[0].Timing.ReferenceClockSource, "/" + Properties.Settings.Default.StimulatorDevice.ToString() + "/PFI0"); if (isNormalRecording) stimTimeTask.Timing.ReferenceClockSource = "/" + Properties.Settings.Default.StimulatorDevice.ToString() + "/PFI0"; else stimTimeTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource; stimTimeTask.Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate; stimTimeTask.Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.RawSampleFrequency / 2)); stimTimeTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( "/" + Properties.Settings.Default.AnalogInDevice[0] + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); stimTimeTask.Control(TaskAction.Verify); // stim Timing Channel settings object StringCollection stimTimePhysChan = new StringCollection(); for (int i = 0; i < stimTimeTask.AIChannels.Count; ++i) { stimTimePhysChan.Add(stimTimeTask.AIChannels[i].PhysicalName); } // Write down the indicies corresponding to the portion of this task that will // actually record stimulus infromation instead of aux analog input stimTimeChanSet = new NRAIChannelCollection(stimTimePhysChan); int[] stimTimeChannels = new int[] { 0, 1 }; stimTimeChanSet.SetupNumericalChannelOnly(stimTimeChannels); // Manually allocate buffer memory //stimTimeTask.Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; Console.WriteLine("NRAcquisitionSetup complete"); } catch (Exception e) { MessageBox.Show(e.Message); } } //Setup scaling coefficients (to convert digital values to voltages) scalingCoeffsSpikes = new List<double[]>(spikeTask.Count); for (int i = 0; i < spikeTask.Count; ++i) scalingCoeffsSpikes.Add(spikeTask[0].AIChannels[0].DeviceScalingCoefficients); if (Properties.Settings.Default.SeparateLFPBoard) scalingCoeffsLFPs = lfpTask.AIChannels[0].DeviceScalingCoefficients; if (Properties.Settings.Default.UseEEG) scalingCoeffsEEG = eegTask.AIChannels[0].DeviceScalingCoefficients; // Setup auxiliary recording tasks if (Properties.Settings.Default.useAuxAnalogInput) { // Set up the aux channel set auxChanSet = new NRAIChannelCollection(Properties.Settings.Default.auxAnalogInChan); if (Properties.Settings.Default.auxAnalogInDev == Properties.Settings.Default.StimInfoDevice && Properties.Settings.Default.RecordStimTimes) { // In this case we are recording both stimulus times and aux analog input times on the same // DAQ, so we need to just make the auxAnInTask reference the stimulus timing task twoAITasksOnSingleBoard = true; auxAnInTask = stimTimeTask; auxChanSet.SetupAuxCollection(ref auxAnInTask); } else { // In this case there is no conflict for AI, so we can create a dedicated task for aux analog input twoAITasksOnSingleBoard = false; auxAnInTask = new Task("AuxiliaryAnalogInput"); auxChanSet.SetupAuxCollection(ref auxAnInTask); auxAnInTask.Timing.ReferenceClockSource = spikeTask[0].Timing.ReferenceClockSource; auxAnInTask.Timing.ReferenceClockRate = spikeTask[0].Timing.ReferenceClockRate; //Pipe ai dev0's sample clock to slave devices auxAnInTask.Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.RawSampleFrequency / 2)); auxAnInTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/Dev1/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); // Manually allocate buffer memory // auxAnInTask.Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; // Create space for the buffer auxAnData = new double[auxChanSet.numericalChannels.Length, spikeBufferLength]; } } if (Properties.Settings.Default.useAuxDigitalInput) { auxDigInTask = new Task("AuxiliaryDigitalInput"); auxDigInTask.DIChannels.CreateChannel(Properties.Settings.Default.auxDigitalInPort, "Auxiliary Digitial In", ChannelLineGrouping.OneChannelForAllLines); auxDigInTask.Timing.ConfigureSampleClock("", spikeSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Convert.ToInt32(Properties.Settings.Default.RawSampleFrequency / 2)); auxDigInTask.Timing.SampleClockSource = spikeTask[0].Timing.SampleClockTerminal; // Manually allocate buffer memory // auxDigInTask.Stream.Buffer.InputBufferSize = DAQ_BUFFER_SIZE_SAMPLES; } #region Setup_Plotting numSnipsDisplayed = (int)numericUpDown_NumSnipsDisplayed.Value; #region PlotData_Buffers //*********************** //Make PlotData buffers //*********************** int downsample, numRows, numCols; const double spikeplotlength = 0.25; //in seconds switch (Properties.Settings.Default.NumChannels) { case 16: numRows = numCols = 4; downsample = 10; break; case 32: numRows = numCols = 6; downsample = 15; break; case 64: numRows = numCols = 8; downsample = 20; //if this gets really small, LFP data won't plot break; default: numRows = numCols = 4; downsample = 5; break; } //Create plot colormap NRBrainbow = (64).GenerateBrainbow(); NRSnipBrainbow = (64).GenerateSnipBrainbow(); NRUnitBrainbow = (64).GenerateUnitBrainbow(); //Initialize graphs if (spikeGraph != null) { spikeGraph.Dispose(); spikeGraph = null; } spikeGraph = new GridGraph(); int samplesPerPlot = (int)(Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * spikeSamplingRate / downsample) * (spikeplotlength / Properties.Settings.Default.ADCPollingPeriodSec)); spikeGraph.setup(numRows, numCols, samplesPerPlot, false, 1 / 4.0, spikeTask[0].AIChannels.All.RangeHigh * 2.0); spikeGraph.setMinMax(0, (float)(samplesPerPlot * numCols) - 1, (float)(spikeTask[0].AIChannels.All.RangeLow * (numRows * 2 - 1)), (float)(spikeTask[0].AIChannels.All.RangeHigh)); spikeGraph.Dock = DockStyle.Fill; spikeGraph.Parent = tabPage_spikes; if (Properties.Settings.Default.UseLFPs) { if (lfpGraph != null) { lfpGraph.Dispose(); lfpGraph = null; } lfpGraph = new RowGraph(); lfpGraph.setup(numChannels, (int)((Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * lfpSamplingRate / downsample) * (5 / Properties.Settings.Default.ADCPollingPeriodSec))), 5.0, spikeTask[0].AIChannels.All.RangeHigh * 2.0); if (Properties.Settings.Default.SeparateLFPBoard) lfpGraph.setMinMax(0, 5 * (int)(Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * lfpSamplingRate / downsample) / Properties.Settings.Default.ADCPollingPeriodSec) - 1, (float)(lfpTask.AIChannels.All.RangeLow * (numChannels * 2 - 1)), (float)(lfpTask.AIChannels.All.RangeHigh)); else lfpGraph.setMinMax(0, 5 * (int)(Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * lfpSamplingRate / downsample) / Properties.Settings.Default.ADCPollingPeriodSec) - 1, (float)(spikeTask[0].AIChannels.All.RangeLow * (numChannels * 2 - 1)), (float)(spikeTask[0].AIChannels.All.RangeHigh)); lfpGraph.Dock = DockStyle.Fill; lfpGraph.Parent = tabPage_LFPs; } if (Properties.Settings.Default.ProcessMUA) { if (muaGraph != null) { muaGraph.Dispose(); muaGraph = null; } muaGraph = new RowGraph(); muaGraph.setup(numChannels, (int)((Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * muaSamplingRate / downsample) * (5 / Properties.Settings.Default.ADCPollingPeriodSec))), 5.0, spikeTask[0].AIChannels.All.RangeHigh * 2.0); muaGraph.setMinMax(0, 5 * (int)(Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * muaSamplingRate / downsample) / Properties.Settings.Default.ADCPollingPeriodSec) - 1, (float)(spikeTask[0].AIChannels.All.RangeLow * (numChannels * 2 - 1)), (float)(spikeTask[0].AIChannels.All.RangeHigh)); muaGraph.Dock = DockStyle.Fill; muaGraph.Parent = tabPage_MUA; muaPlotData = new PlotDataRows(numChannels, downsample, (int)(muaSamplingRate * 5), muaSamplingRate, (float)spikeTask[0].AIChannels.All.RangeHigh * 2F, 0.5, 5, Properties.Settings.Default.ADCPollingPeriodSec); //muaPlotData.setGain(Properties.Settings.Default.LFPDisplayGain); //muaGraph.setDisplayGain(Properties.Settings.Default.LFPDisplayGain); muaPlotData.dataAcquired += new PlotData.dataAcquiredHandler(muaPlotData_dataAcquired); } if (Properties.Settings.Default.UseEEG) { if (eegGraph != null) { eegGraph.Dispose(); eegGraph = null; } eegGraph = new RowGraph(); eegGraph.setup(Properties.Settings.Default.EEGNumChannels, (int)((Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * eegSamplingRate / downsample) * (5 / Properties.Settings.Default.ADCPollingPeriodSec))), 5.0, eegTask.AIChannels.All.RangeHigh * 2.0); eegGraph.setMinMax(0, 5 * (int)(Math.Ceiling(Properties.Settings.Default.ADCPollingPeriodSec * eegSamplingRate / downsample) / Properties.Settings.Default.ADCPollingPeriodSec) - 1, (float)(eegTask.AIChannels.All.RangeLow * (Properties.Settings.Default.EEGNumChannels * 2 - 1)), (float)(eegTask.AIChannels.All.RangeHigh)); eegGraph.Dock = DockStyle.Fill; eegGraph.Parent = tabPage_EEG; } resetSpkWfm(); //Take care of spike waveform graph double ampdec = (1 / Properties.Settings.Default.PreAmpGain); spikePlotData = new PlotDataGrid(numChannels, downsample, (int)(spikeSamplingRate), spikeSamplingRate, (float)(spikeTask[0].AIChannels.All.RangeHigh * 2.0), numRows, numCols, spikeplotlength, Properties.Settings.Default.ChannelMapping, Properties.Settings.Default.ADCPollingPeriodSec); spikePlotData.dataAcquired += new PlotData.dataAcquiredHandler(spikePlotData_dataAcquired); spikePlotData.setGain(Properties.Settings.Default.SpikeDisplayGain); spikeGraph.setDisplayGain(Properties.Settings.Default.SpikeDisplayGain); if (Properties.Settings.Default.UseLFPs) { if (Properties.Settings.Default.SeparateLFPBoard) lfpPlotData = new PlotDataRows(numChannels, downsample, (int)(lfpSamplingRate * 5), lfpSamplingRate, (float)lfpTask.AIChannels.All.RangeHigh * 2F, 0.5, 5, Properties.Settings.Default.ADCPollingPeriodSec); else lfpPlotData = new PlotDataRows(numChannels, downsample, (int)(lfpSamplingRate * 5), lfpSamplingRate, (float)spikeTask[0].AIChannels.All.RangeHigh * 2F, 0.5, 5, Properties.Settings.Default.ADCPollingPeriodSec); lfpPlotData.setGain(Properties.Settings.Default.LFPDisplayGain); lfpGraph.setDisplayGain(Properties.Settings.Default.LFPDisplayGain); lfpPlotData.dataAcquired += new PlotData.dataAcquiredHandler(lfpPlotData_dataAcquired); } waveformPlotData = new EventPlotData(numChannels, spikeDet.NumPre + spikeDet.NumPost + 1, (float)(spikeTask[0].AIChannels.All.RangeHigh * 2F), numRows, numCols, numSnipsDisplayed, Properties.Settings.Default.ChannelMapping); waveformPlotData.setGain(Properties.Settings.Default.SpkWfmDisplayGain); spkWfmGraph.setDisplayGain(Properties.Settings.Default.SpkWfmDisplayGain); waveformPlotData.dataAcquired += new EventPlotData.dataAcquiredHandler(waveformPlotData_dataAcquired); waveformPlotData.start(); #endregion if (Properties.Settings.Default.UseEEG) { eegPlotData = new PlotDataRows(Properties.Settings.Default.EEGNumChannels, downsample, (int)(eegSamplingRate * 5), eegSamplingRate, (float)eegTask.AIChannels.All.RangeHigh * 2F, 0.5, 5, Properties.Settings.Default.ADCPollingPeriodSec); eegPlotData.setGain(Properties.Settings.Default.EEGDisplayGain); eegGraph.setDisplayGain(Properties.Settings.Default.EEGDisplayGain); eegPlotData.dataAcquired += new PlotData.dataAcquiredHandler(eegPlotData_dataAcquired); } if (Properties.Settings.Default.useAuxAnalogInput) { // Remove existing plots for (int i = scatterGraph_AuxAnalogData.Plots.Count-1; i > 0; --i) { scatterGraph_AuxAnalogData.Plots.RemoveAt(i); } // Initialize the aux data scatter graph with a plot for each aux Analog channel for (int i = 0; i < Properties.Settings.Default.auxAnalogInChan.Count-1; ++i) { ScatterPlot p = new ScatterPlot(); scatterGraph_AuxAnalogData.Plots.Add(p); } // Initialize the controller auxInputGraphController = new ScatterGraphController(ref scatterGraph_AuxAnalogData); // Make history selector reflect current limits on input //slide_AnalogDispMaxVoltage.Range = new Range(0.05, 10); //slide_AnalogDispWidth.Range = new Range(2*Properties.Settings.Default.ADCPollingPeriodSec, Properties.Settings.Default.datSrvBufferSizeSec); } #endregion #region Setup_Filters //Setup filters, based on user's input resetSpikeFilter(); if (Properties.Settings.Default.UseLFPs) resetLFPFilter(); resetEEGFilter(); muaFilter = new Filters.MUAFilter( numChannels, spikeSamplingRate, spikeBufferLength, Properties.Settings.Default.MUAHighCutHz, Properties.Settings.Default.MUAFilterOrder, MUA_DOWNSAMPLE_FACTOR, Properties.Settings.Default.ADCPollingPeriodSec); #endregion #region Setup_DataStorage //Initialize data storing matrices // numChannels = Properties.Settings.Default.NumChannels; numSpikeReads = new int[spikeTask.Count]; filtSpikeData = new rawType[numChannels][]; if (Properties.Settings.Default.UseLFPs) { filtLFPData = new rawType[numChannels][]; finalLFPData = new rawType[numChannels][]; for (int i = 0; i < filtSpikeData.GetLength(0); ++i) { if (Properties.Settings.Default.SeparateLFPBoard) filtLFPData[i] = new rawType[lfpBufferLength]; else filtLFPData[i] = new rawType[spikeBufferLength]; } } if (Properties.Settings.Default.ProcessMUA) { muaData = new double[numChannels][]; for (int c = 0; c < numChannels; ++c) muaData[c] = new double[spikeBufferLength / MUA_DOWNSAMPLE_FACTOR]; } if (Properties.Settings.Default.UseEEG) { filtEEGData = new double[Properties.Settings.Default.EEGNumChannels][]; for (int i = 0; i < filtEEGData.GetLength(0); ++i) { filtEEGData[i] = new double[eegBufferLength]; } } for (int i = 0; i < filtSpikeData.GetLength(0); ++i) { filtSpikeData[i] = new rawType[spikeBufferLength]; if (Properties.Settings.Default.UseLFPs) finalLFPData[i] = new rawType[lfpBufferLength]; } if (Properties.Settings.Default.UseStimulator) { stimDataBuffer = new double[STIM_BUFFER_LENGTH]; stimJump = (double)spikeSamplingRate * 0.0001; //num. indices in 100 us of data } stimIndices = new List<StimTick>(5); //if devices refresh rate is reset, need to reset SALPA if (checkBox_SALPA.Checked) resetSALPA(); if (spikeDet != null && isNormalRecording) setSpikeDetector(); if (spikeDet.spikeDetector == null) setSpikeDetector(); #endregion #region Verify Tasks if (Properties.Settings.Default.UseStimulator && Properties.Settings.Default.RecordStimTimes) stimTimeTask.Control(TaskAction.Verify); if (Properties.Settings.Default.UseEEG) eegTask.Control(TaskAction.Verify); if (Properties.Settings.Default.SeparateLFPBoard && Properties.Settings.Default.UseLFPs) lfpTask.Control(TaskAction.Verify); if (checkBox_video.Checked) triggerTask.Control(TaskAction.Verify); for (int i = 0; i < spikeTask.Count; ++i) spikeTask[i].Control(TaskAction.Verify); if (Properties.Settings.Default.useAuxAnalogInput) auxAnInTask.Control(TaskAction.Verify); if (Properties.Settings.Default.useAuxDigitalInput) auxDigInTask.Control(TaskAction.Verify); #endregion SetupFileWriting(); //Set callbacks for data acq. spikeReader = new List<AnalogMultiChannelReader>(spikeTask.Count); for (int i = 0; i < spikeTask.Count; ++i) { spikeReader.Add(new AnalogMultiChannelReader(spikeTask[i].Stream)); spikeReader[i].SynchronizeCallbacks = true; } //if (Properties.Settings.Default.UseSingleChannelPlayback) // spikeOutWriter = new AnalogSingleChannelWriter(spikeOutTask.Stream); if (checkBox_video.Checked) triggerWriter = new DigitalSingleChannelWriter(triggerTask.Stream); //if (Properties.Settings.Default.UseSingleChannelPlayback) // spikeOutWriter.SynchronizeCallbacks = false; //These don't use UI, so they don't need to be synched spikeCallback = new AsyncCallback(AnalogInCallback_spikes); if (Properties.Settings.Default.UseStimulator && Properties.Settings.Default.RecordStimTimes) { stimTimeReader = new AnalogMultiChannelReader(stimTimeTask.Stream); } if (Properties.Settings.Default.SeparateLFPBoard && Properties.Settings.Default.UseLFPs) { lfpReader = new AnalogUnscaledReader(lfpTask.Stream); lfpReader.SynchronizeCallbacks = true; lfpCallback = new AsyncCallback(AnalogInCallback_LFPs); } if (Properties.Settings.Default.UseEEG) { eegReader = new AnalogUnscaledReader(eegTask.Stream); eegReader.SynchronizeCallbacks = true; eegCallback = new AsyncCallback(AnalogInCallback_EEG); } if (Properties.Settings.Default.useAuxAnalogInput) { auxAnReader = new AnalogMultiChannelReader(auxAnInTask.Stream); auxAnReader.SynchronizeCallbacks = true; auxAnCallback = new AsyncCallback(AnalogInCallback_AuxAn); } if (Properties.Settings.Default.useAuxDigitalInput) { auxDigReader = new DigitalSingleChannelReader(auxDigInTask.Stream); auxDigReader.SynchronizeCallbacks = true; auxDigCallback = new AsyncCallback(AnalogInCallback_AuxDig); } //Setup background workers for data processing bwSpikes = new List<BackgroundWorker>(spikeTask.Count); bwIsRunning = new bool[spikeTask.Count]; for (int i = 0; i < spikeTask.Count; ++i) { bwSpikes.Add(new BackgroundWorker()); bwSpikes[i].DoWork += new DoWorkEventHandler(bwSpikes_DoWork); bwSpikes[i].RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwSpikes_RunWorkerCompleted); bwSpikes[i].WorkerSupportsCancellation = true; } //Make persistent buffers for spikeData spikeData = new List<AnalogWaveform<double>[]>(spikeReader.Count); for (int i = 0; i < spikeReader.Count; ++i) { spikeData.Add(new AnalogWaveform<double>[numChannelsPerDev]); for (int j = 0; j < numChannelsPerDev; ++j) spikeData[i][j] = new AnalogWaveform<double>(spikeBufferLength); } //Make channel playback task if (Properties.Settings.Default.UseSingleChannelPlayback) BNCOutput = new ChannelOutput(spikeSamplingRate, 0.1, Properties.Settings.Default.ADCPollingPeriodSec, spikeTask[0], Properties.Settings.Default.SingleChannelPlaybackDevice, 0); } catch (Exception exception) { //Display Errors this.Cursor = Cursors.Default; MessageBox.Show(exception.Message); reset(); } // Set up the DataSrv object. This is an object that publishes a nice large data history // for use in closed loop control and other things if (datSrv != null) datSrv = null; datSrv = new DataSrv( Properties.Settings.Default.datSrvBufferSizeSec, checkBox_SALPA.Checked, SALPA_WIDTH, checkBox_spikesFilter.Checked, spikeDet.spikeDetectionLag ); // Set the number of units if appropriate if (spikeDet.spikeSorter != null) datSrv.SetNumberOfUnits(spikeDet.spikeSorter.totalNumberOfUnits, spikeDet.spikeSorter.unit2Channel); Debugger = new Logger(); Debugger.GrabTimer(spikeTask[0]); //Send debug output to the user's application data folder Debugger.SetPath(Path.Combine(Properties.Settings.Default.neurorighterAppDataPath, "neurorighter-log.txt")); //Tell neuroRighter that the tasks now exist taskRunning = true; } else { Console.WriteLine("NRAcquisitionSetup was called while a task was running, and therefore setup did not execute. Perhaps this should have thrown an error"); } } //update gui at the end // Modify the UI, so user doesn't try running multiple instances of tasks spikeDet.numPreSamples.Enabled = false; spikeDet.numPostSamples.Enabled = false; settingsToolStripMenuItem.Enabled = false; button_Train.Enabled = false; button_SetRecordingStreams.Enabled = false; switch_record.Enabled = false; //processingSettingsToolStripMenuItem.Enabled = false; button_startStimFromFile.Enabled = false; button_startClosedLoopStim.Enabled = false; checkBox_SALPA.Enabled = false; //numericUpDown_NumSnipsDisplayed.Enabled = false; button_startClosedLoopStim.Enabled = false; button_scaleUp.Enabled = true; button_scaleDown.Enabled = true; button_scaleReset.Enabled = true; // Disable spike detector saving while running spikeDet.DisableFileMenu(); Console.WriteLine("NRAcquisitionSetup successfully executed"); this.Cursor = Cursors.Default; return false; }