From 8d8aef13b245db7d4833ebb9a0f95f4b3402ee10 Mon Sep 17 00:00:00 2001 From: jvoigts <jvoigts@mit.edu> Date: Sun, 16 Jun 2013 19:22:22 -0400 Subject: [PATCH] Added simple event display --- .../Visualization/LfpDisplayCanvas.cpp | 156 +++++++++++++++++- .../Visualization/LfpDisplayCanvas.h | 48 +++++- 2 files changed, 192 insertions(+), 12 deletions(-) diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.cpp b/Source/Processors/Visualization/LfpDisplayCanvas.cpp index a1ea23d11..54f91aacb 100755 --- a/Source/Processors/Visualization/LfpDisplayCanvas.cpp +++ b/Source/Processors/Visualization/LfpDisplayCanvas.cpp @@ -107,6 +107,21 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) : lfpDisplay->setNumChannels(nChans); lfpDisplay->setRange(1000.0f); + // add event display-specific controls (currently just an enable/disable button) + for (int i = 0; i < 8; i++) + { + + + eventDisplayInterface* eventOptions = new eventDisplayInterface(lfpDisplay, this, i); + eventDisplayInterfaces.add(eventOptions); + addAndMakeVisible(eventOptions); + eventOptions->setBounds(500+(floor(i/2)*20), getHeight()-20-(i%2)*20, 40, 20); + + lfpDisplay->setEventDisplayState(i,true); + + } + + } LfpDisplayCanvas::~LfpDisplayCanvas() @@ -127,6 +142,13 @@ void LfpDisplayCanvas::resized() timebaseSelection->setBounds(175,getHeight()-30,100,25); spreadSelection->setBounds(345,getHeight()-30,100,25); + for (int i = 0; i < 8; i++) + { + eventDisplayInterfaces[i]->setBounds(500+(floor(i/2)*20), getHeight()-20-(i%2)*20, 40, 20); // arrange event channel buttons in two rows + eventDisplayInterfaces[i]->repaint(); + } + + // std::cout << "Canvas thinks LfpDisplay should be this high: " // << lfpDisplay->getTotalHeight() << std::endl; @@ -293,7 +315,7 @@ void LfpDisplayCanvas::updateScreenBuffer() screenBuffer->clear(screenBufferIndex, 1); - for (int channel = 0; channel < nChans; channel++) + for (int channel = 0; channel <= nChans; channel++) // pull one extra channel for event display { screenBuffer->addFrom(channel, // destChannel @@ -339,6 +361,11 @@ float LfpDisplayCanvas::getXCoord(int chan, int samp) return samp; } +int LfpDisplayCanvas::getNumChannels() +{ + return nChans; +} + float LfpDisplayCanvas::getYCoord(int chan, int samp) { return *screenBuffer->getSampleData(chan, samp); @@ -383,6 +410,10 @@ void LfpDisplayCanvas::paint(Graphics& g) g.drawText("Timebase (s)",175,getHeight()-55,300,20,Justification::left, false); g.drawText("Spread (px)",345,getHeight()-55,300,20,Justification::left, false); + g.drawText("Event display",500,getHeight()-55,300,20,Justification::left, false); + + + } void LfpDisplayCanvas::refresh() @@ -523,6 +554,12 @@ LfpDisplay::~LfpDisplay() deleteAllChildren(); } + +int LfpDisplay::getNumChannels() +{ + return numChans; +} + void LfpDisplay::setNumChannels(int numChannels) { numChans = numChannels; @@ -539,7 +576,7 @@ void LfpDisplay::setNumChannels(int numChannels) //std::cout << "Adding new channel display." << std::endl; - LfpChannelDisplay* lfpChan = new LfpChannelDisplay(canvas, i); + LfpChannelDisplay* lfpChan = new LfpChannelDisplay(canvas, this, i); lfpChan->setColour(channelColours[i % channelColours.size()]); lfpChan->setRange(range); @@ -549,7 +586,7 @@ void LfpDisplay::setNumChannels(int numChannels) channels.add(lfpChan); - LfpChannelDisplayInfo* lfpInfo = new LfpChannelDisplayInfo(canvas, i); + LfpChannelDisplayInfo* lfpInfo = new LfpChannelDisplayInfo(canvas, this, i); lfpInfo->setColour(channelColours[i % channelColours.size()]); lfpInfo->setRange(range); @@ -750,10 +787,24 @@ void LfpDisplay::mouseDown(const MouseEvent& event) } + +bool LfpDisplay::setEventDisplayState(int ch, bool state) +{ + eventDisplayEnabled[ch] = state; + return eventDisplayEnabled[ch]; +} + + +bool LfpDisplay::getEventDisplayState(int ch) +{ + return eventDisplayEnabled[ch]; +} + + // ------------------------------------------------------------------ -LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, int channelNumber) : - canvas(c), isSelected(false), chan(channelNumber), channelHeight(40), channelOverlap(300), range(1000.0f) +LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, LfpDisplay* d, int channelNumber) : + canvas(c), display(d), isSelected(false), chan(channelNumber), channelHeight(40), channelOverlap(300), range(1000.0f) { channelHeightFloat = (float) channelHeight; @@ -777,6 +828,9 @@ void LfpChannelDisplay::paint(Graphics& g) g.setColour(Colours::yellow); // draw most recent drawn sample position g.drawLine(canvas->screenBufferIndex+1, 0, canvas->screenBufferIndex+1, getHeight()); + + + //g.setColour(Colours::red); // draw oldest drawn sample position //g.drawLine(canvas->lastScreenBufferIndex, 0, canvas->lastScreenBufferIndex, getHeight()-channelOverlap); @@ -803,7 +857,6 @@ void LfpChannelDisplay::paint(Graphics& g) int stepSize = 1; int from = 0; // for vertical line drawing in the LFP data int to = 0; - g.setColour(lineColour); //for (int i = 0; i < getWidth()-stepSize; i += stepSize) // redraw entire display int ifrom = canvas->lastScreenBufferIndex - 3; // need to start drawing a bit before the actual redraw windowfor the interpolated line to join correctly @@ -823,6 +876,24 @@ void LfpChannelDisplay::paint(Graphics& g) for (int i = ifrom; i < ito ; i += stepSize) // redraw only changed portion { + // draw event markers + int rawEventState = canvas->getYCoord(canvas->getNumChannels(), i);// get last channel+1 in buffer (represents events) + for (int ev_ch = 0; ev_ch < 8 ; ev_ch++) // for all event channels + { + if (display->getEventDisplayState(ev_ch)){ // check if plotting for this channel is enabled + if ( rawEventState & (1 << ev_ch)){ // events are representet by a bit code, so we have to extract the individual bits with a mask + g.setColour(display->channelColours[ev_ch*2]); // get color from lfp color scheme + g.setOpacity(0.25f); + g.drawLine(i, center-channelHeight/2 , i, center+channelHeight/2); + } + } + } + + //std::cout << "e " << canvas->getYCoord(canvas->getNumChannels()-1, i) << std::endl; + + g.setColour(lineColour); + g.setOpacity(1); + // drawLine makes for ok anti-aliased plots, but is pretty slow g.drawLine(i, (canvas->getYCoord(chan, i)/range*channelHeightFloat)+getHeight()/2, @@ -873,6 +944,10 @@ void LfpChannelDisplay::paint(Graphics& g) } + + + + void LfpChannelDisplay::setRange(float r) { range = r; @@ -929,8 +1004,8 @@ int LfpChannelDisplay::getChannelOverlap() // ------------------------------- -LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, int ch) - : LfpChannelDisplay(canvas_, ch) +LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, LfpDisplay* display_, int ch) + : LfpChannelDisplay(canvas_, display_, ch) { } @@ -949,4 +1024,67 @@ void LfpChannelDisplayInfo::paint(Graphics& g) } - \ No newline at end of file + + +// Event display Options -------------------------------------------------------------------- + +eventDisplayInterface::eventDisplayInterface(LfpDisplay* display_, LfpDisplayCanvas* canvas_, int chNum): + isEnabled(true), display(display_), canvas(canvas_) +{ + + channelNumber=chNum; + + chButton = new UtilityButton(String(channelNumber+1), Font("Small Text", 13, Font::plain)); + chButton->setRadius(5.0f); + chButton->setBounds(4,4,14,14); + chButton->setEnabledState(true); + chButton->setCorners(true, false, true, false); + //chButton.color = display->channelColours[channelNumber*2]; + chButton->addListener(this); + addAndMakeVisible(chButton); + + + checkEnabledState(); + +} + +eventDisplayInterface::~eventDisplayInterface() +{ + +} + +void eventDisplayInterface::checkEnabledState() +{ + isEnabled = display->getEventDisplayState(channelNumber); + + //repaint(); +} + +void eventDisplayInterface::buttonClicked(Button* button) +{ + checkEnabledState(); + if (isEnabled){ + display->setEventDisplayState(channelNumber, false); + } else { + display->setEventDisplayState(channelNumber, true); + } + + repaint(); + +} + + +void eventDisplayInterface::paint(Graphics& g) +{ + + checkEnabledState(); + + if (isEnabled){ + g.setColour(display->channelColours[channelNumber*2]); + g.fillRoundedRectangle(2,2,18,18,5.0f); + } + + + //g.drawText(String(channelNumber), 8, 2, 200, 15, Justification::left, false); + +} \ No newline at end of file diff --git a/Source/Processors/Visualization/LfpDisplayCanvas.h b/Source/Processors/Visualization/LfpDisplayCanvas.h index cfbe69b13..79f903e24 100755 --- a/Source/Processors/Visualization/LfpDisplayCanvas.h +++ b/Source/Processors/Visualization/LfpDisplayCanvas.h @@ -33,6 +33,7 @@ class LfpTimescale; class LfpDisplay; class LfpChannelDisplay; class LfpChannelDisplayInfo; +class eventDisplayInterface; /** @@ -68,6 +69,8 @@ public: int getChannelHeight(); + int getNumChannels(); + float getXCoord(int chan, int samp); float getYCoord(int chan, int samp); @@ -117,6 +120,9 @@ private: StringArray timebases; StringArray spreads; // option for vertical spacing between channels + OwnedArray<eventDisplayInterface> eventDisplayInterfaces; + + void refreshScreenBuffer(); void updateScreenBuffer(); @@ -161,6 +167,7 @@ public: ~LfpDisplay(); void setNumChannels(int numChannels); + int getNumChannels(); int getTotalHeight(); @@ -180,6 +187,12 @@ public: void setChannelHeight(int r); int getChannelHeight(); + bool setEventDisplayState(int ch, bool state); + bool getEventDisplayState(int ch); + + + Array<Colour> channelColours; + private: int numChans; @@ -190,7 +203,8 @@ private: Array<LfpChannelDisplay*> channels; Array<LfpChannelDisplayInfo*> channelInfo; - Array<Colour> channelColours; + + bool eventDisplayEnabled[8]; float range; @@ -199,7 +213,7 @@ private: class LfpChannelDisplay : public Component { public: - LfpChannelDisplay(LfpDisplayCanvas*, int channelNumber); + LfpChannelDisplay(LfpDisplayCanvas*, LfpDisplay*, int channelNumber); ~LfpChannelDisplay(); void paint(Graphics& g); @@ -223,6 +237,7 @@ public: protected: LfpDisplayCanvas* canvas; + LfpDisplay* display; bool isSelected; @@ -243,10 +258,37 @@ protected: class LfpChannelDisplayInfo : public LfpChannelDisplay { public: - LfpChannelDisplayInfo(LfpDisplayCanvas*, int channelNumber); + LfpChannelDisplayInfo(LfpDisplayCanvas*, LfpDisplay*, int channelNumber); + + void paint(Graphics& g); + +}; + +class eventDisplayInterface : public Component, + public Button::Listener +{ +public: + eventDisplayInterface(LfpDisplay*, LfpDisplayCanvas*, int chNum); + ~eventDisplayInterface(); void paint(Graphics& g); + void buttonClicked(Button* button); + + void checkEnabledState(); + +private: + + int channelNumber; + + bool isEnabled; + + LfpDisplay* display; + LfpDisplayCanvas* canvas; + + ScopedPointer<UtilityButton> chButton; + }; + #endif // __LFPDISPLAYCANVAS_H_B711873A__ -- GitLab