/* ------------------------------------------------------------------ This file is part of the Open Ephys GUI Copyright (C) 2013 Open Ephys ------------------------------------------------------------------ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* */ #include "EvntTrigAvgCanvas.h" EvntTrigAvgCanvas::EvntTrigAvgCanvas(EvntTrigAvg* n) : processor(n) { clearHisto = new UtilityButton("CLEAR", Font("Default", 12, Font::plain)); clearHisto->addListener(this); clearHisto->setRadius(3.0f); clearHisto->setBounds(80,5,65,15); clearHisto->setClickingTogglesState(false); addAndMakeVisible(clearHisto); setWantsKeyboardFocus(true); viewport = new Viewport(); viewport->setScrollBarsShown(true,true); scrollBarThickness = viewport->getScrollBarThickness(); int yOffset = 50; processor = n; display = new EvntTrigAvgDisplay(this, viewport, n); display->setBounds(0,100,getWidth()-scrollBarThickness, getHeight()-yOffset-40); //removeChildComponent(scale); scale = new Timescale(processor->getWindowSize(),processor->getSampleRate(),data,bin,binSize); //holder = new EvntTrigAvgCanvasHolder(processor,processor->getWindowSize(),processor->getSampleRate(),data,bin,binSize); viewport->setViewedComponent(display,false); addAndMakeVisible(viewport); viewport->setBounds(0,100,getWidth(), getHeight()-yOffset-40); //holder->setBounds(0, getHeight(), getWidth(), 40); scale->setBounds(0, getHeight()-40, getWidth()-scrollBarThickness, 40); //addAndMakeVisible(scale,false); addAndMakeVisible(scale,true); update(); } EvntTrigAvgCanvas::~EvntTrigAvgCanvas() { //delete scale; //deleteAllChildren(); } void EvntTrigAvgCanvas::beginAnimation() { std::cout << "EvntTrigAvgCanvas beginning animation." << std::endl; startCallbacks(); } void EvntTrigAvgCanvas::endAnimation() { std::cout << "EvntTrigAvgCanvas ending animation." << std::endl; stopCallbacks(); } void EvntTrigAvgCanvas::update() { repaint(); } void EvntTrigAvgCanvas::refreshState() { resized(); } void EvntTrigAvgCanvas::resized() { int yOffset = 50; viewport->setBounds(0,yOffset,getWidth(),getHeight()-yOffset-40); if (display->getNumGraphs()>0) display->setBounds(0,yOffset,getWidth()-scrollBarThickness,display->getNumGraphs()*40); else display->setBounds(0,100,getWidth()-scrollBarThickness, getHeight()-yOffset-40); scale->setBounds(0, getHeight()-40, getWidth()-scrollBarThickness, 40); repaint(); } void EvntTrigAvgCanvas::paint(Graphics& g) { g.fillAll(Colours::darkgrey); int width=getWidth(); int height=getHeight(); int drawWidth = width-20-width/4; int xOffset= 20; int yOffset = 50; g.setColour(Colours::lightgrey); g.fillRoundedRectangle(getWidth()-scrollBarThickness, yOffset, scrollBarThickness, height-2*yOffset, 4.0); g.setColour(Colours::snow); g.drawText("Electrode",5, 5, width/8, 20, juce::Justification::left); g.drawText("Trials: " + String(processor->getLastTTLCalculated()),(xOffset+drawWidth)/2-50,5,100,20,Justification::centred); g.drawText("Min.", width-180-scrollBarThickness, 5, 60, 20, Justification::right); g.drawText("Max", width-120-scrollBarThickness, 5, 60, 20, Justification::right); g.drawText("Mean", width-60-scrollBarThickness, 5, 60, 20, Justification::right); //delete scale; //scale = new Timescale(processor->getWindowSize(),processor->getSampleRate(),data,bin,processor->getBinSize()); //removeChildComponent(scale); scale = new Timescale(processor->getWindowSize(),processor->getSampleRate(),data,bin,processor->getBinSize()); scale->setBounds(0, getHeight()-40, width-scrollBarThickness, 40); addAndMakeVisible(scale,true); repaint(); } void EvntTrigAvgCanvas::repaintDisplay(){ display->repaint(); } void EvntTrigAvgCanvas::refresh() { // called every 10 Hz display->refresh(); // dont know if this ever gets called repaint(); } bool EvntTrigAvgCanvas::keyPressed(const KeyPress& key) { return false; } void EvntTrigAvgCanvas::buttonClicked(Button* button) { if (button == clearHisto){ histoData.clear(); minMaxMean.clear(); processor->setParameter(4,0); } repaint(); } void EvntTrigAvgCanvas::setBin(int bin_){ bin = bin_; } void EvntTrigAvgCanvas::setBinSize(int binSize_){ binSize = binSize_; } void EvntTrigAvgCanvas::setData(int data_){ data=data_; } //-------------------------------------------------------------------- EvntTrigAvgDisplay::EvntTrigAvgDisplay(EvntTrigAvgCanvas* c, Viewport* v, EvntTrigAvg* p){ processor=p; canvas=c; viewport=v; addMouseListener(this, true); channelColours[0]=Colour(224,185,36); channelColours[1]=Colour(214,210,182); channelColours[2]=Colour(243,119,33); channelColours[3]=Colour(186,157,168); channelColours[4]=Colour(237,37,36); channelColours[5]=Colour(179,122,79); channelColours[6]=Colour(217,46,171); channelColours[7]=Colour(217, 139,196); channelColours[8]=Colour(101,31,255); channelColours[9]=Colour(141,111,181); channelColours[10]=Colour(48,117,255); channelColours[11]=Colour(184,198,224); channelColours[12]=Colour(116,227,156); channelColours[13]=Colour(150,158,155); channelColours[14]=Colour(82,173,0); channelColours[15]=Colour(125,99,32); } EvntTrigAvgDisplay::~EvntTrigAvgDisplay(){ deleteAllChildren(); } void EvntTrigAvgDisplay::visibleAreaChanged(const Rectangle<int>& newVisibleArea){ } void EvntTrigAvgDisplay::viewedComponentChanged(Component* newComponent){ } void EvntTrigAvgDisplay::resized() { int width = getWidth(); for(int i = 0 ; i < graphs.size() ; i++){ graphs[i]->setBounds(20, 40*(i+1), width-20-width/4, 40); graphs[i]->resized(); } } void EvntTrigAvgDisplay::paint(Graphics &g) { histoData.clear(); histoData = processor->getHistoData(); minMaxMean.clear(); minMaxMean = processor->getMinMaxMean(); int width=getWidth(); g.setColour(Colours::snow); std::vector<String> labels = processor->getElectrodeLabels(); deleteAllChildren(); graphs.clear(); int graphCount = 0; for (int i = 0 ; i < histoData.size() ; i++){ GraphUnit* graph; ScopedLock myScopedLock(*processor->getMutex()); if(histoData[i][1]==0){ // if sortedId == 0 graph = new GraphUnit(processor,canvas,channelColours[(histoData[i][0]+sizeof(channelColours))%(sizeof(channelColours))],labels[histoData[i][0]],&minMaxMean[i][2],&histoData[i][2]); // pass &histoData[i][2] instead of 3 to pass on how many bins are used } else{ graph = new GraphUnit(processor,canvas,channelColours[(histoData[i][0]+sizeof(channelColours))%(sizeof(channelColours))],"ID "+String(histoData[i][1]),&minMaxMean[i][2],&histoData[i][2]); } graphs.push_back(graph); graph->setBounds(0, 40*(graphCount), width-20, 40); addAndMakeVisible(graph,true); graphCount += 1; } repaint(); // ideally find better method than this } void EvntTrigAvgDisplay::refresh() { for (int i = 0 ; i < graphs.size() ; i++){ graphs[i]->repaint(); } } int EvntTrigAvgDisplay::getNumGraphs() { return graphs.size(); } //-------------------------------------------------------------------- Timescale::Timescale(int windowSize_, uint64 sampleRate_, int data_, int bin_,int binSize_) { windowSize = windowSize_; sampleRate = sampleRate_; data = data_; bin = bin_; binSize = binSize_; } Timescale::~Timescale() { deleteAllChildren(); } void Timescale::paint(Graphics& g) { g.setColour(Colours::snow); int histogramLen = getWidth()-230; int vertLineLen = 20; int textStart = vertLineLen+5; g.drawHorizontalLine(0, 30, histogramLen+30); g.drawVerticalLine(30, 0, vertLineLen); g.drawText(String(-1000.0*float(windowSize/2)/float(sampleRate)) + " ms", 0, textStart, 60, 10, Justification::centred); g.drawVerticalLine(histogramLen/4+30, 0, vertLineLen); g.drawText(String(-1000.0*float(windowSize/2)/2.0/float(sampleRate)) + " ms", histogramLen/4, textStart, 60, 10, Justification::centred); g.drawVerticalLine(histogramLen/2+30, 0, vertLineLen); g.drawText(" 0 ms",histogramLen/2, textStart, 60, 10, Justification::centred); g.drawVerticalLine(3*histogramLen/4+30, 0, vertLineLen); g.drawText(String(1000.0*float(windowSize/2)/2.0/float(sampleRate)) + " ms", 3*histogramLen/4, textStart, 60, 10, Justification::centred); g.drawVerticalLine(histogramLen+30, 0, vertLineLen); g.drawText(String(1000.0*float(windowSize/2)/float(sampleRate)) + " ms", histogramLen, textStart, 60, 10, Justification::centred); g.drawText(String(1000*float(bin*binSize)/float(sampleRate)) + "-" + String(1000*(float(bin+1)*binSize)/float(sampleRate)) + "ms, Spikes: " + String(data),histogramLen+30, 5, getWidth()-(histogramLen+30), getHeight(), Justification::right); } void Timescale::resized() { } void Timescale::update(int windowSize_, uint64 sampleRate_) { windowSize=windowSize_; sampleRate=sampleRate_; } void inline Timescale::setBin(int bin_) { bin = bin_; } void inline Timescale::setData(int data_) { data = data_; } void inline Timescale::setBinSize(int binSize_) { binSize = binSize_; } //-------------------------------------------------------------------- GraphUnit::GraphUnit(EvntTrigAvg* processor_, EvntTrigAvgCanvas* canvas_,juce::Colour color_, String name_, float * stats_,uint64 * data_){ ScopedLock myScopedLock(*processor_->getMutex()); color = color_; LD = new LabelDisplay(color_,name_); LD->setBounds(0,0,30,40); addAndMakeVisible(LD,false); HG = new HistoGraph(processor_,canvas_,color_,data_[0], stats_[1], &data_[1]); HG->setBounds(30,0,getWidth()-210,40); addAndMakeVisible(HG,false); SD = new StatDisplay(processor_,color_,stats_); SD->setBounds(getWidth()-180,0,180,40); addAndMakeVisible(SD,false); } GraphUnit::~GraphUnit() { deleteAllChildren(); } void GraphUnit::paint(Graphics& g) { //g.setOpacity(1); } void GraphUnit::resized() { LD->setBounds(0,0,30,40); SD->setBounds(getWidth()-180,0,180,40); HG->setBounds(30,0,getWidth()-210,40); } //---------------- LabelDisplay::LabelDisplay(juce::Colour color_, String name_) { color = color_; name = name_; } LabelDisplay::~LabelDisplay() { deleteAllChildren(); } void LabelDisplay::paint(Graphics& g) { g.setColour(color); g.drawText(name,0, 0, 30, 40, juce::Justification::left); } void LabelDisplay::resized() { } //---------------- HistoGraph::HistoGraph(EvntTrigAvg* processor_,EvntTrigAvgCanvas* canvas_, juce::Colour color_, uint64 bins_, float max_, uint64 * histoData_) { color = color_; histoData = histoData_; bins = bins_; max = uint64(max_); processor=processor_; canvas = canvas_; } HistoGraph::~HistoGraph() { deleteAllChildren(); } void HistoGraph::paint(Graphics& g) { g.setColour(Colours::snow); g.setOpacity(0.5); g.drawVerticalLine(getWidth()/2,5, getHeight()); g.setColour(color); for (int i = 1 ; i < bins ; i++){ ScopedLock myScopedLock(*processor->getMutex()); if(max!=0){ g.drawLine(float(i-1)*float(getWidth())/float(bins),getHeight()-(histoData[i-1]*getHeight()/max),float(i)*float(getWidth())/float(bins),getHeight()-(histoData[i]*getHeight()/max)); } else g.drawLine(float(i-1)*float(getWidth())/float(bins),getHeight()-(histoData[i-1]*getHeight()),float(i)*float(getWidth())/float(bins),getHeight()-(histoData[i]*getHeight())); } } void HistoGraph::resized() { repaint(); } void HistoGraph::select() { } void HistoGraph::deselect() { } void HistoGraph::clear() { } void HistoGraph::mouseMove(const MouseEvent &event) { if(bins>0){ int posX = event.x; ScopedLock myScopedLock(*processor->getMutex()); int valueY = histoData[int(float(posX)/float(getWidth())*float(bins))]; canvas->setData(valueY); canvas->setBin(int(float(posX)/float(getWidth())*float(bins))-(bins/2)); canvas->repaint(); } } //---------------- StatDisplay::StatDisplay(EvntTrigAvg* processor_, juce::Colour c, float * s) { processor=processor_; color = c; stats = s; } StatDisplay::~StatDisplay() { deleteAllChildren(); } void StatDisplay::paint(Graphics& g) { ScopedLock myScopedLock(*processor->getMutex()); g.setColour(color); g.drawText(String(stats[0]),0, 0, 60, 40, juce::Justification::right); g.drawText(String(stats[1]),60, 0, 60, 40, juce::Justification::right); g.drawText(String(stats[2]),120, 0, 60, 40, juce::Justification::right); } void StatDisplay::resized() { }