Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

NeuronMonitor.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2005 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  ***************************************************************************/
00007 
00008 //SpikeStream includes
00009 #include "NeuronMonitor.h"
00010 #include "Debug.h"
00011 #include "NeuronMonitorXmlHandler.h"
00012 #include "SpikeStreamMainWindow.h"
00013 #include "SimulationWidget.h"
00014 
00015 //Qt includes
00016 #include <qlayout.h>
00017 #include <qxml.h>
00018 #include <qmessagebox.h>
00019 #include <qcolor.h>
00020 #include <qpainter.h>
00021 
00022 //Qwt includes
00023 #include <qwt_plot_curve.h>
00024 #include <qwt_plot_layout.h>
00025 
00026 //Other includes
00027 #include <iostream>
00028 using namespace std;
00029 
00030 
00031 //Number of items in dataset
00032 #define DEFAULT_MONITOR_DATASET_SIZE 100
00033 
00034 
00035 /* Class that draws the background of the plot - easier to put it here than a separate file! */
00036 class Background: public QwtPlotItem {
00037         public:
00038                 Background(){
00039                         setZ(0.0);
00040                         QColor colour(255, 255, 255);
00041                         brush = new QBrush(colour, Qt::SolidPattern);
00042                 }
00043                 ~Background(){
00044                         delete brush;
00045                 }
00046 
00047                 virtual int rtti() const {
00048                         return QwtPlotItem::Rtti_PlotUserItem;
00049                 }
00050 
00051                 virtual void draw(QPainter *painter, const QwtScaleMap &, const QwtScaleMap &yMap, const QRect &rect) const {
00052                         painter->fillRect(rect, *brush);
00053                 }
00054         private:
00055                 QBrush* brush;
00056 };
00057 
00058 
00059 /* Constructor for monitoring neuron data
00060         The main initialisation work is done when the setUpGraphs method is called after the information
00061         about the monitored data has been received by the simulationManager. */
00062 NeuronMonitor::NeuronMonitor(QWidget *parent, QString neuronGrpDesc, unsigned int neurID, unsigned int neurGrpID) : QDialog(parent, "NeurMonDlg", false){
00063         neuronMonitoring = true;
00064         
00065         //Store neuron ID and group
00066         neuronID = neurID;
00067         neuronGrpID = neurGrpID;
00068 
00069         //Store parent class as a widget to avoid include problems
00070         simulationWidget = parent;
00071 
00072         //Set caption
00073         QString captionStr = "Monitoring neuron ";
00074         captionStr += QString::number(neurID) += " in neuron group ";
00075         captionStr += neuronGrpDesc;
00076         this->setCaption(captionStr);
00077 
00078         //Create box to organise dialog
00079         verticalBox = new QVBoxLayout(this, 2, 2);
00080 
00081         //Add temporary label explaining that we are waiting for neuron information.
00082         loadingLabel = new QLabel("Loading graphs, please wait.", this);
00083         verticalBox->addWidget(loadingLabel);
00084 
00085         this->show();
00086 }
00087 
00088 /* Constructor for monitoring synapse data
00089         The main initialisation work is done when the setUpGraphs method is called after the information
00090         about the monitored data has been received by the simulationManager. */
00091 NeuronMonitor::NeuronMonitor(QWidget *parent, unsigned int neurGrpID, unsigned int fromNeurID, unsigned int toNeurID) : QDialog(parent, "NeurMonDlg", false){
00092         neuronMonitoring = false;
00093 
00094         //Store neuron ID and group
00095         fromNeuronID = fromNeurID;
00096         toNeuronID = toNeurID;
00097         neuronGrpID = neurGrpID;
00098 
00099         //Store parent class as a widget to avoid include problems
00100         simulationWidget = parent;
00101 
00102         //Set caption
00103         QString captionStr = "Monitoring synapse ";
00104         captionStr += QString::number(neurID) += " in neuron group ";
00105         captionStr += neuronGrpDesc;
00106         this->setCaption(captionStr);
00107 
00108         //Create box to organise dialog
00109         verticalBox = new QVBoxLayout(this, 2, 2);
00110 
00111         //Add temporary label explaining that we are waiting for neuron information.
00112         loadingLabel = new QLabel("Loading graphs, please wait.", this);
00113         verticalBox->addWidget(loadingLabel);
00114 
00115         this->show();
00116 }
00117 
00118 //Destructor
00119 NeuronMonitor::~NeuronMonitor(){
00120         #ifdef MEMORY_DEBUG
00121                 cout<<"DESTROYING MONITOR DATA PLOTTER"<<endl;
00122         #endif//MEMORY_DEBUG
00123 }
00124 
00125 
00126 //--------------------------------------------------------------------------------
00127 //----------------------      PUBLIC METHODS       -------------------------------
00128 //--------------------------------------------------------------------------------
00129 
00130 /* Adds a graph to the display. Usually called by NeuronMonitorXmlHandler, which in turn is invoked 
00131         by simulationManager running as a separate thread. */
00132 void NeuronMonitor::addGraph(NewGraph newGraph){
00133         cout<<"MONITOR DATA PLOTTER ADDING GRAPH "<<newGraph.description<<" range from "<<newGraph.rangeLow<<" to "<<newGraph.rangeHigh<<endl;
00134 
00135         //Lock mutex because this method is invoked by a separate thread
00136         SpikeStreamMainWindow::spikeStreamApplication->lock();
00137 
00138         //Create a plot
00139         QwtPlot* tempPlot = new QwtPlot(this, "Temp Curve");
00140         verticalBox->addWidget(tempPlot);
00141 
00142         //Set titles on the axes
00143     tempPlot->setAxisTitle(QwtPlot::yLeft, newGraph.description);
00144         tempPlot->setAxisTitle(QwtPlot::xBottom, "Time (ms)");
00145 
00146         //Add background
00147     Background *bg = new Background();
00148     bg->attach(tempPlot);
00149 
00150         //Create a curve for the plot
00151         QwtPlotCurve *tempCurve = new QwtPlotCurve("Curve 1");
00152         QColor redColor(255, 0, 0);
00153         QBrush tmpBrush(redColor, Qt::Dense4Pattern);
00154     tempCurve->setBrush(tmpBrush);
00155         QPen tmpPen(redColor);
00156         tempCurve->setPen(tmpPen);
00157 
00158         //Create a new dataset to manage the data for this graph
00159         MonitorDataset* tempData = new MonitorDataset(DEFAULT_MONITOR_DATASET_SIZE, newGraph.rangeLow, newGraph.rangeHigh);
00160 
00161         //Pass a reference to the dataset to the curve
00162         tempCurve->setData(*tempData);
00163         
00164         //Attach the curve to the plot
00165         tempCurve->attach(tempPlot);
00166         
00167         //Refresh the plot
00168         tempPlot->replot();
00169 
00170         //Make plot visible.
00171         tempPlot->show();
00172 
00173         //Store reference to new dataset
00174         dataVector.push_back(tempData);
00175 
00176         //Store reference to new plot
00177         plotVector.push_back(tempPlot);
00178 
00179         //Unlock mutex
00180         SpikeStreamMainWindow::spikeStreamApplication->unlock();
00181 }
00182 
00183 
00184 //Called when the dialog needs to be closed by an external class. */
00185 void NeuronMonitor::closeDialog(){
00186         cout<<"MONITOR DATA PLOTTER CLOSING closeDialog()"<<endl;
00187         this->accept();
00188 }
00189 
00190 
00191 /* Adds the data in the float array to the graphs */
00192 void NeuronMonitor::plotData(double time, const double* dataArray, int arrayLength){
00193         //Lock mutex because this method is invoked by a separate thread
00194         SpikeStreamMainWindow::spikeStreamApplication->lock();
00195 
00196         //Double check that arrayLength is the same as the vector lengths
00197         if(arrayLength != plotVector.size()){
00198                 QMessageBox::critical(this, "Monitor Error", "Data and graphs do not match!");
00199                 return;
00200         }
00201 
00202         //Add the data to the plots and replot the graph
00203         for(int i=0; i<arrayLength; ++i){
00204                 dataVector[i]->addPoint(time, dataArray[i]);
00205                 plotVector[i]->replot();
00206         }
00207 
00208         //Unlock mutex
00209         SpikeStreamMainWindow::spikeStreamApplication->unlock();
00210 }       
00211 
00212 
00213 /* The char array is an XML file containing the set up information for the graphs.
00214         This method parses the information and creates the graphs. */
00215 void NeuronMonitor::setUpGraphs(const char* charArray){
00216         QString xmlString(charArray);
00217         QXmlInputSource xmlInput;
00218         xmlInput.setData(xmlString);
00219         MonitorXmlHandler monXmlHandler(this);
00220     QXmlSimpleReader reader;
00221         reader.setContentHandler(&monXmlHandler);
00222         reader.setErrorHandler(&monXmlHandler);
00223         reader.parse(xmlInput);
00224 }
00225 
00226 
00227 /* Called when all graphs have been loaded so that loading label can be hidden. */
00228 void NeuronMonitor::loadingComplete(){
00229         loadingLabel->hide();
00230 }
00231 
00232 //--------------------------------------------------------------------------------
00233 //----------------------      PROTECTED METHODS       ----------------------------
00234 //--------------------------------------------------------------------------------
00235 
00236 /* Called when user closes the dialog. Instructs simulation to stop sending monitor data. 
00237         Dialog is closed programmatically by the closeDialog() method, which may trigger this. */
00238 
00239 void NeuronMonitor::closeEvent ( QCloseEvent * e ){
00240         cout<<"NEURON MONITOR CLOSING closeEvent()"<<endl;
00241 
00242         //Lock mutex because this method is invoked by a separate thread
00243         SpikeStreamMainWindow::spikeStreamApplication->lock();
00244 
00245         //Tell simulationManager to stop monitoring neuron or synapse
00246         if(neuronMonitoring)
00247                 ((SimulationWidget*)simulationWidget)->getSimulationManager()->stopNeuronMonitoring(neuronGrpID, neuronID);
00248         else
00249                 ((SimulationWidget*)simulationWidget)->getSimulationManager()->stopSynapseMonitoring(neuronGrpID, fromNeuronID, toNeuronID);
00250 
00251         //Unlock mutex
00252         SpikeStreamMainWindow::spikeStreamApplication->unlock();
00253 
00254         this->accept();
00255 }
00256 
00257 
00258 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4