diff --git a/Source/Processors/Editors/SpikeDisplayEditor.cpp b/Source/Processors/Editors/SpikeDisplayEditor.cpp index 7d731c313dea089944481dd1ad595b259024a935..565967fa5b872b97228370d7918d68d384fa40eb 100755 --- a/Source/Processors/Editors/SpikeDisplayEditor.cpp +++ b/Source/Processors/Editors/SpikeDisplayEditor.cpp @@ -29,15 +29,15 @@ SpikeDisplayEditor::SpikeDisplayEditor(GenericProcessor* parentNode) : VisualizerEditor(parentNode,200) { - // Get the number of sub channels from the parentNode - // Assume all plots have the same number of subChannels - // Otherwise we'll have to track the number of subChannels - nSubChannels = 4; + // // Get the number of sub channels from the parentNode + // // Assume all plots have the same number of subChannels + // // Otherwise we'll have to track the number of subChannels + // nSubChannels = 4; - for (int i=0; i<nSubChannels; i++) - subChanSelected[i] = true; + // for (int i=0; i<nSubChannels; i++) + // subChanSelected[i] = true; - initializeButtons(); + // initializeButtons(); tabText = "Spikes"; @@ -197,72 +197,72 @@ void SpikeDisplayEditor::buttonCallback(Button* button) { //std::cout<<"Got event from component:"<<button<<std::endl; - int pIdx = 0; - if (button == panUpBtn) - { - for (int i=0; i<nSubChannels; i++) - if (subChanSelected[i]) - canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, 1); - } - else if (button == panDownBtn) - { - for (int i=0; i<nSubChannels; i++) - if (subChanSelected[i]) - canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, -1); - } - else if (button == zoomInBtn) - { - for (int i=0; i<nSubChannels; i++) - if (subChanSelected[i]) - canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, -1); - } - else if (button == zoomOutBtn) - { - for (int i=0; i<nSubChannels; i++) - if (subChanSelected[i]) - canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, 1); - } - - else if (button == clearBtn) - { - std::cout<<"Clear!"<<std::endl; - canvas->setParameter(SPIKE_CMD_CLEAR_ALL, 0); - } - else if (button == saveImgBtn) - std::cout<<"Save!"<<std::endl; - - // toggle all sub channel buttons - else if (button == allSubChansBtn) - { - bool b = allSubChansBtn->getToggleState(); - for (int i=0; i<nSubChannels; i++) - subChanBtn[i]->setToggleState(b, true); - - } - // Check the sub Channel selection buttons one by one - else - { - // If the user has clicked a sub channel button then the all channels button should be untoggled if toggled - allSubChansBtn->setToggleState(false, false); - for (int i=0; i<nSubChannels; i++) - if (button == subChanBtn[i]) - { - std::cout<<"SubChannel:"<<i<< " set to:"; - subChanSelected[i] = ((UtilityButton*) button)->getToggleState(); - std::cout<< subChanSelected[i]<<std::endl; - } - - // If the user has toggled all of the sub channels on, then set AllChans to on - bool allChansToggled = true; - for (int i=0; i<nSubChannels; i++) - { - if (subChanBtn[i]->getToggleState()!=allChansToggled) - { - allChansToggled = false; - break; - } - } - allSubChansBtn->setToggleState(allChansToggled, false); - - } + // int pIdx = 0; + // if (button == panUpBtn) + // { + // for (int i=0; i<nSubChannels; i++) + // if (subChanSelected[i]) + // canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, 1); + // } + // else if (button == panDownBtn) + // { + // for (int i=0; i<nSubChannels; i++) + // if (subChanSelected[i]) + // canvas->setParameter(SPIKE_CMD_PAN_AXES, pIdx, i, -1); + // } + // else if (button == zoomInBtn) + // { + // for (int i=0; i<nSubChannels; i++) + // if (subChanSelected[i]) + // canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, -1); + // } + // else if (button == zoomOutBtn) + // { + // for (int i=0; i<nSubChannels; i++) + // if (subChanSelected[i]) + // canvas->setParameter(SPIKE_CMD_ZOOM_AXES, pIdx, i, 1); + // } + + // else if (button == clearBtn) + // { + // std::cout<<"Clear!"<<std::endl; + // canvas->setParameter(SPIKE_CMD_CLEAR_ALL, 0); + // } + // else if (button == saveImgBtn) + // std::cout<<"Save!"<<std::endl; + + // // toggle all sub channel buttons + // else if (button == allSubChansBtn) + // { + // bool b = allSubChansBtn->getToggleState(); + // for (int i=0; i<nSubChannels; i++) + // subChanBtn[i]->setToggleState(b, true); + + // } + // // Check the sub Channel selection buttons one by one + // else + // { + // // If the user has clicked a sub channel button then the all channels button should be untoggled if toggled + // allSubChansBtn->setToggleState(false, false); + // for (int i=0; i<nSubChannels; i++) + // if (button == subChanBtn[i]) + // { + // std::cout<<"SubChannel:"<<i<< " set to:"; + // subChanSelected[i] = ((UtilityButton*) button)->getToggleState(); + // std::cout<< subChanSelected[i]<<std::endl; + // } + + // // If the user has toggled all of the sub channels on, then set AllChans to on + // bool allChansToggled = true; + // for (int i=0; i<nSubChannels; i++) + // { + // if (subChanBtn[i]->getToggleState()!=allChansToggled) + // { + // allChansToggled = false; + // break; + // } + // } + // allSubChansBtn->setToggleState(allChansToggled, false); + + // } } diff --git a/Source/Processors/SpikeDisplayNode.h b/Source/Processors/SpikeDisplayNode.h index c6343cba1b3b802a0a541577a2cfc62348c1c859..54922440afe86becbe2164eed36ae1e62591c93c 100755 --- a/Source/Processors/SpikeDisplayNode.h +++ b/Source/Processors/SpikeDisplayNode.h @@ -30,11 +30,6 @@ #include "GenericProcessor.h" #include "Visualization/SpikeObject.h" -#define SPIKE_CMD_CLEAR_ALL 10000 -#define SPIKE_CMD_CLEAR_SEL 10001 -#define SPIKE_CMD_PAN_AXES 10002 -#define SPIKE_CMD_ZOOM_AXES 10003 - class DataViewport; /** @@ -88,8 +83,6 @@ private: ScopedPointer<MidiBuffer> eventBuffer; - //std::queue<SpikeObject> spikebuffer; - int bufferSize; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SpikeDisplayNode); diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp index f2d226eb9ecf6e4e541e9cf764e4d717aafcfc41..10412a3d434ae5fa763dcb9fa8bd8f210ee8309f 100755 --- a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp +++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp @@ -48,160 +48,6 @@ SpikeDisplayCanvas::~SpikeDisplayCanvas() } -// void SpikeDisplayCanvas::initializeSpikePlots(){ - -// std::cout<<"Initializing Plots"<<std::endl; - -// // This layout system really only works if plot types are aggregated together. -// // It might be worthwhile to investigate the merits of using a grid system -// // The canvas is defined as N grid widths wide. Each SpikePlot defines its -// // dimensions in grid widths. -// // -// // Plots are added from left to right, top to bottom. A plot is put into place -// // if it can fit into the next grid location w/o its top going above the current -// // row and w/o its bottom going below the current row -// // -// // This would lead to dead space but it would allow the plots to all scale accoring -// // to how much space they need. The current system of deciding plot sizes, isn't going -// // to scale well.... this needs more thought - -// // if (plots.size() != nPlots) -// // { - -// // int totalWidth = getWidth(); - -// // int plotWidth = (totalWidth - yBuffer * ( nCols+1)) / nCols + .99; -// // int plotHeight = plotWidth / 2 + .5; -// // int rowCount = 0; - -// // plots.clear(); - -// // for (int i = 0; i < nPlots; i++) -// // { -// // int pType; -// // switch (processor->getNumberOfChannelsForElectrode(i)){ -// // case 1: -// // pType = SINGLE_PLOT; -// // break; -// // case 2: -// // pType = STEREO_PLOT; -// // break; -// // case 4: -// // pType = TETRODE_PLOT; -// // break; -// // default: -// // pType = SINGLE_PLOT; -// // break; -// // } - -// // // bool use_generic_plots_flag = true; - -// // // BaseUIElement *sp; - -// // // if (use_generic_plots_flag) -// // SpikePlot *sp = new SpikePlot(xBuffer + i%nCols * (plotWidth + xBuffer) , -// // yBuffer + rowCount * (plotHeight + yBuffer), -// // plotWidth, plotHeight, pType); - -// // // else -// // // sp = new StereotrodePlot(xBuffer + i%nCols * (plotWidth + xBuffer) , -// // // yBuffer + rowCount * (plotHeight + yBuffer), -// // // plotWidth, plotHeight); -// // plots.add(sp); - -// // if (i%nCols == nCols-1) -// // rowCount++; -// // } -// // //totalHeight = rowCount * (plotHeight + yBuffer) + yBuffer * 2; -// // // Set the total height of the Canvas to the top of the top most plot - -// // plotsInitialized = true; -// // repositionSpikePlots(); -// // } -// } - -// void SpikeDisplayCanvas::repositionSpikePlots(){ - -// // int canvasWidth = getWidth(); -// // int gridSize = canvasWidth / nCols; - -// // gridSize = (gridSize > MIN_GRID_SIZE) ? gridSize : MIN_GRID_SIZE; -// // gridSize = (gridSize < MAX_GRID_SIZE) ? gridSize : MAX_GRID_SIZE; - - - -// // int x = xBuffer; -// // int y = getHeight() - yBuffer; -// // int p = 0; -// // int w,h; -// // int yIncrement = 0; -// // bool loopCheck = false; -// // //std::cout<<"Positioning Spike Plots"<<std::endl; -// // while (p < plots.size()){ - -// // // Ask the current plot for its desired dims -// // plots[p]->getBestDimensions(&w, &h); -// // w *= gridSize; -// // h *= gridSize; - -// // // Check to see if plot exceeds width of canvas, if yes, set x back to 0 and go to the bottom most plot on the canvas -// // if ( (x + w + xBuffer > canvasWidth - xBuffer) && !loopCheck){ -// // //std::cout<<"Collision with the edge of the canvas, going down a row"<<std::endl; -// // x = xBuffer; -// // y = y - yIncrement - yBuffer; -// // yIncrement = 0; -// // loopCheck = true; -// // continue; -// // } -// // // else place the plot -// // else{ -// // //std::cout<<"Positioning p:"<<p<<" at "<<x<<","<<y - h<<" "<<w<<","<<h<<std::endl; -// // // plots[p]->setPosition(x, y - h + getScrollAmount(), w, h); -// // x = x + w + xBuffer; - -// // // set a new minimum -// // if (h > yIncrement) -// // yIncrement = h; - -// // // increment p -// // p++; -// // loopCheck = false; -// // } -// // } - -// // // int plotWidth = (totalWidth - yBuffer * ( nCols+1)) / nCols + .99; -// // // int plotHeight = plotWidth / 2 + .5; -// // // int rowCount = 0; - -// // // for (int i=0; i < plots.size(); i++) -// // // { -// // // -// // // plots[i]->setPosition( xBuffer + i%nCols * (plotWidth + xBuffer) , -// // // getHeight() - ( yBuffer + plotHeight + rowCount * (plotHeight + yBuffer)) + getScrollAmount(), -// // // plotWidth, -// // // plotHeight); // deprecated conversion from string constant to char -// // // -// // // if (i%nCols == nCols-1) -// // // rowCount++; -// // // } - -// // // Set the total height of the Canvas to the top of the top most plot -// // // totalHeight = (rowCount + 1) * (plotHeight + yBuffer) + yBuffer; -// // totalHeight = getHeight() + (y + yIncrement); -// } - -// void SpikeDisplayCanvas::newOpenGLContextCreated() -// { -// std::cout<<"SpikeDisplayCanvas::newOpenGLContextCreated()"<<std::endl; -// setUp2DCanvas(); -// activateAntiAliasing(); -// disablePointSmoothing(); - -// glClearColor (0.667, 0.698, 0.718, 1.0); -// resized(); -// //endAnimation(); -// } - void SpikeDisplayCanvas::beginAnimation() { std::cout << "Beginning animation." << std::endl; @@ -262,6 +108,8 @@ void SpikeDisplayCanvas::paint(Graphics& g) void SpikeDisplayCanvas::refresh() { processSpikeEvents(); + + repaint(); } void SpikeDisplayCanvas::processSpikeEvents() @@ -285,22 +133,22 @@ void SpikeDisplayCanvas::processSpikeEvents() int nSamples = (bufferSize-4)/2; SpikeObject newSpike; - SpikeObject simSpike; + //SpikeObject simSpike; unpackSpike(&newSpike, dataptr, bufferSize); - int chan = newSpike.source; + int electrodeNum = newSpike.source; - generateSimulatedSpike(&simSpike, 0, 0); + // generateSimulatedSpike(&simSpike, 0, 0); - for (int i = 0; i < newSpike.nChannels * newSpike.nSamples; i++) - { - simSpike.data[i] = newSpike.data[i%80] + 5000;// * 3 - 10000; - } + // for (int i = 0; i < newSpike.nChannels * newSpike.nSamples; i++) + // { + // simSpike.data[i] = newSpike.data[i%80] + 5000;// * 3 - 10000; + // } - simSpike.nSamples = 40; + // simSpike.nSamples = 40; - spikeDisplay->plotSpike(simSpike); + spikeDisplay->plotSpike(newSpike, electrodeNum); } @@ -310,28 +158,12 @@ void SpikeDisplayCanvas::processSpikeEvents() } - // ---------------------------------------------------------------- SpikeDisplay::SpikeDisplay(SpikeDisplayCanvas* sdc, Viewport* v) : canvas(sdc), viewport(v) { - // for (int i = 0; i < 4; i++) - // { - // addSpikePlot(2, i); - // } - - // for (int i = 0; i < 4; i++) - // { - // addSpikePlot(1, i); - // } - - // for (int i = 0; i < 4; i++) - // { - // addSpikePlot(4, i); - // } - totalHeight = 1000; } @@ -366,9 +198,7 @@ void SpikeDisplay::paint(Graphics& g) void SpikeDisplay::resized() { - // this is kind of a mess -- is there any way to optimize? - - //std::cout << "Resizing spike display" << std::endl; + // this is kind of a mess -- is there any way to optimize it? if (spikePlots.size() > 0) { @@ -448,7 +278,7 @@ void SpikeDisplay::resized() } - totalHeight = 5000; + totalHeight = 5000; // don't even deal with making the display the correct height if (totalHeight < getHeight()) { @@ -463,9 +293,9 @@ void SpikeDisplay::mouseDown(const MouseEvent& event) } -void SpikeDisplay::plotSpike(const SpikeObject& spike) +void SpikeDisplay::plotSpike(const SpikeObject& spike, int electrodeNum) { - + spikePlots[electrodeNum]->processSpikeObject(spike); } @@ -540,12 +370,13 @@ void SpikePlot::paint(Graphics& g) } -void SpikePlot::processSpikeObject(SpikeObject s) +void SpikePlot::processSpikeObject(const SpikeObject& s) { //std::cout<<"ElectrodePlot::processSpikeObject()"<<std::endl; + for (int i = 0; i < nWaveAx; i++) wAxes[i]->updateSpikeData(s); - // wAxes[1].updateSpikeData(s); + for (int i = 0; i < nProjAx; i++) pAxes[i]->updateSpikeData(s); } @@ -770,104 +601,52 @@ void SpikePlot::n2ProjIdx(int proj, int* p1, int* p2) // -------------------------------------------------- -// TetrodePlot::TetrodePlot(SpikeDisplayCanvas* sdc, int elecNum) : -// SpikePlot(sdc, elecNum, 4) -// { - -// for (int i = 0; i < numChannels; i++) -// { -// WaveformPlot* wp = new WaveformPlot(); -// addAndMakeVisible(wp); -// waveformPlots.add(wp); -// } - -// for (int i = 0; i < 6; i++) -// { -// ProjectionPlot* pp = new ProjectionPlot(); -// addAndMakeVisible(pp); -// projectionPlots.add(pp); -// } - -// } - -// void TetrodePlot::resized() -// { -// float w = (float) getWidth() / 5.0f; -// float h = (float) getHeight() / 2.0f; - -// waveformPlots[0]->setBounds(0, 0, w, h); -// waveformPlots[1]->setBounds(w, 0, w, h); -// waveformPlots[2]->setBounds(0, h, w, h); -// waveformPlots[3]->setBounds(w, h, w, h); - -// projectionPlots[0]->setBounds(w*2, 0, w, h); -// projectionPlots[1]->setBounds(w*3, 0, w, h); -// projectionPlots[2]->setBounds(w*4, 0, w, h); -// projectionPlots[3]->setBounds(w*2, h, w, h); -// projectionPlots[4]->setBounds(w*3, h, w, h); -// projectionPlots[5]->setBounds(w*4, h, w, h); - -// } - -// StereotrodePlot::StereotrodePlot(SpikeDisplayCanvas* sdc, int elecNum) : -// SpikePlot(sdc, elecNum, 2) -// { - -// for (int i = 0; i < numChannels; i++) -// { -// WaveformPlot* wp = new WaveformPlot(); -// addAndMakeVisible(wp); -// waveformPlots.add(wp); -// } - -// ProjectionPlot* pp = new ProjectionPlot(); -// addAndMakeVisible(pp); -// projectionPlots.add(pp); - -// } - -// void StereotrodePlot::resized() -// { -// float w = (float) getWidth() / 3.0f; -// float h = (float) getHeight() / 1.0f; - -// waveformPlots[0]->setBounds(0, 0, w, h); -// waveformPlots[1]->setBounds(w, 0, w, h); - -// projectionPlots[0]->setBounds(w*2, 0, w, h); +WaveAxes::WaveAxes(int channel) : GenericAxes(channel) +{ -// } +} -// SingleElectrodePlot::SingleElectrodePlot(SpikeDisplayCanvas* sdc, int elecNum) : -// SpikePlot(sdc, elecNum, 1) -// { +void WaveAxes::paint(Graphics& g) +{ + g.setColour(Colours::black); + g.fillRect(5,5,getWidth()-10, getHeight()-10); -// WaveformPlot* wp = new WaveformPlot(); -// addAndMakeVisible(wp); -// waveformPlots.add(wp); + int chan = 0; -// } + // if no spikes have been received then don't plot anything + if (!gotFirstSpike) + { + return; + } -// void SingleElectrodePlot::resized() -// { -// float w = (float) getWidth() / 1.0f; -// float h = (float) getHeight() / 1.0f; + // draw the grid lines for the waveforms + // if (drawGrid) + // drawWaveformGrid(s.threshold[chan], s.gain[chan]); -// waveformPlots[0]->setBounds(0, 0, w, h); + // compute the spatial width for each waveform sample + //compute the spatial width for each waveform sample + float dx = getWidth()/s.nSamples; + float x = 0; -// } + // type corresponds to channel so we need to calculate the starting + // sample based upon which channel is getting plotted + int sampIdx = s.nSamples * type; // + + // draw the individual waveform points + g.setColour(Colours::white); -// ----------------------------------------------------- + int dSamples = 1; -WaveAxes::WaveAxes(int channel) : GenericAxes(channel) -{ + for (int i = 0; i < s.nSamples-1; i++) + { + //std::cout << s.data[sampIdx] << std::endl; + g.drawLine(x, (s.data[sampIdx]-32768)/100, x+dx, (s.data[sampIdx+1]-32768)/100); + sampIdx += dSamples; + x += dx; + } -} + // draw the threshold line and labels -void WaveAxes::paint(Graphics& g) -{ - g.setColour(Colours::black); - g.fillRect(5,5,getWidth()-5, getHeight()-5); } void WaveAxes::clear() @@ -914,7 +693,7 @@ GenericAxes::~GenericAxes() } -void GenericAxes::updateSpikeData(SpikeObject newSpike) +void GenericAxes::updateSpikeData(const SpikeObject& newSpike) { if (!gotFirstSpike) { diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.h b/Source/Processors/Visualization/SpikeDisplayCanvas.h index 9bbde7868687a1c36b288ddc42ac1c6abe4cae26..539845f1aca2a20d4f3e8f00a252643596b17ea0 100755 --- a/Source/Processors/Visualization/SpikeDisplayCanvas.h +++ b/Source/Processors/Visualization/SpikeDisplayCanvas.h @@ -123,7 +123,7 @@ public: void mouseDown(const MouseEvent& event); - void plotSpike(const SpikeObject& spike); + void plotSpike(const SpikeObject& spike, int electrodeNum); int getTotalHeight() {return totalHeight;} @@ -165,7 +165,7 @@ public: void select(); void deselect(); - void processSpikeObject(SpikeObject s); + void processSpikeObject(const SpikeObject& s); SpikeDisplayCanvas* canvas; @@ -191,7 +191,7 @@ private: int plotType; int nWaveAx; int nProjAx; - + bool limitsChanged; double limits[MAX_N_CHAN][2]; @@ -209,44 +209,6 @@ private: }; - -// class TetrodePlot : public SpikePlot -// { -// public: -// TetrodePlot(SpikeDisplayCanvas*, int elecNum); -// ~TetrodePlot() {} - -// void resized(); - -// private: - -// }; - -// class StereotrodePlot : public SpikePlot -// { -// public: -// StereotrodePlot(SpikeDisplayCanvas*, int elecNum); -// ~StereotrodePlot() {} - -// void resized(); - -// private: - -// }; - -// class SingleElectrodePlot : public SpikePlot -// { -// public: -// SingleElectrodePlot(SpikeDisplayCanvas*, int elecNum); -// ~SingleElectrodePlot() {} - -// void resized(); - -// private: - -// }; - - /** Base class for drawing axes for spike visualization. @@ -263,7 +225,7 @@ public: virtual ~GenericAxes(); - void updateSpikeData(SpikeObject s); + void updateSpikeData(const SpikeObject& s); void setXLims(double xmin, double xmax); void getXLims(double* xmin, double* xmax);