00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "MonitorDataPlotter.h"
00025 #include "Debug.h"
00026 #include "MonitorXmlHandler.h"
00027 #include "SpikeStreamMainWindow.h"
00028 #include "SimulationWidget.h"
00029
00030
00031 #include <qlayout.h>
00032 #include <qxml.h>
00033 #include <qmessagebox.h>
00034 #include <qcolor.h>
00035 #include <qpainter.h>
00036
00037
00038 #include <qwt_plot_curve.h>
00039 #include <qwt_plot_layout.h>
00040
00041
00042 #include <iostream>
00043 using namespace std;
00044
00045
00046
00047 #define DEFAULT_MONITOR_DATASET_SIZE 100
00048
00049
00050
00051 class Background: public QwtPlotItem {
00052 public:
00053 Background(){
00054 setZ(0.0);
00055 QColor colour(255, 255, 255);
00056 brush = new QBrush(colour, Qt::SolidPattern);
00057 }
00058 ~Background(){
00059 delete brush;
00060 }
00061
00062 virtual int rtti() const {
00063 return QwtPlotItem::Rtti_PlotUserItem;
00064 }
00065
00066 virtual void draw(QPainter *painter, const QwtScaleMap&, const QwtScaleMap&, const QRect &rect) const {
00067 painter->fillRect(rect, *brush);
00068 }
00069 private:
00070 QBrush* brush;
00071 };
00072
00073
00074
00075
00076
00077 MonitorDataPlotter::MonitorDataPlotter(QWidget *parent, QString neuronGrpDesc, unsigned int neurGrpID, unsigned int neurID) : QDialog(parent, "NeurMonDlg", false){
00078 neuronMonitoring = true;
00079
00080
00081 neuronID = neurID;
00082 neuronGrpID = neurGrpID;
00083
00084
00085 simulationWidget = parent;
00086
00087
00088 QString captionStr = "Monitoring neuron ";
00089 captionStr += QString::number(neurID) += " in neuron group ";
00090 captionStr += neuronGrpDesc;
00091 this->setCaption(captionStr);
00092
00093
00094 verticalBox = new QVBoxLayout(this, 2, 2);
00095
00096
00097 loadingLabel = new QLabel("Loading graphs, please wait.", this);
00098 verticalBox->addWidget(loadingLabel);
00099
00100
00101 axisFont = new QFont( "Arial", 8);
00102 axisTitleFont = new QFont("Arial", 9, QFont::Bold);
00103
00104
00105 parseError = false;
00106
00107 this->show();
00108 }
00109
00110
00111
00112
00113
00114 MonitorDataPlotter::MonitorDataPlotter(QWidget *parent, unsigned int neurGrpID, unsigned int fromNeurID, unsigned int toNeurID) : QDialog(parent, "MonDlg", false){
00115 neuronMonitoring = false;
00116
00117
00118 fromNeuronID = fromNeurID;
00119 toNeuronID = toNeurID;
00120 neuronGrpID = neurGrpID;
00121
00122
00123 simulationWidget = parent;
00124
00125
00126 QString captionStr = "Monitoring synapse from ";
00127 captionStr += QString::number(fromNeuronID) += " to ";
00128 captionStr += QString::number(toNeuronID) += " in neuron group ";
00129 captionStr += QString::number(neuronGrpID);
00130 this->setCaption(captionStr);
00131
00132
00133 verticalBox = new QVBoxLayout(this, 2, 2);
00134
00135
00136 loadingLabel = new QLabel("Loading graphs, please wait.", this);
00137 verticalBox->addWidget(loadingLabel);
00138
00139
00140 axisFont = new QFont( "Arial", 8);
00141 axisTitleFont = new QFont("Arial", 9, QFont::Bold);
00142
00143
00144 parseError = false;
00145
00146 this->show();
00147 }
00148
00149
00150
00151 MonitorDataPlotter::~MonitorDataPlotter(){
00152 #ifdef MEMORY_DEBUG
00153 cout<<"DESTROYING MONITOR DATA PLOTTER"<<endl;
00154 #endif//MEMORY_DEBUG
00155
00156
00157 for(vector<QwtPlot*>::iterator iter = plotVector.begin(); iter != plotVector.end(); ++iter)
00158 delete *iter;
00159
00160
00161 for(vector<MonitorDataset*>::iterator iter = dataVector.begin(); iter != dataVector.end(); ++iter){
00162 (*iter)->cleanUp();
00163 delete *iter;
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 void MonitorDataPlotter::addGraph(NewGraph newGraph){
00175 #ifdef GRAPH_LOAD_DEBUG
00176 cout<<"MonitorDataPlotter: Adding graph: "<<newGraph.description<<" range from "<<newGraph.rangeLow<<" to "<<newGraph.rangeHigh<<endl;
00177 #endif//GRAPH_LOAD_DEBUG
00178
00179
00180 SpikeStreamMainWindow::spikeStreamApplication->lock();
00181
00182
00183 QwtPlot* tempPlot = new QwtPlot(this, "Temp Curve");
00184 tempPlot->setMinimumSize(120, 120);
00185
00186
00187 tempPlot->setAxisFont(QwtPlot::xBottom, *axisFont);
00188 tempPlot->setAxisFont(QwtPlot::yLeft, *axisFont);
00189
00190
00191 tempPlot->setAutoReplot(false);
00192
00193
00194 verticalBox->addWidget(tempPlot);
00195
00196
00197 QwtText yText(newGraph.description);
00198 yText.setFont(*axisTitleFont);
00199 tempPlot->setAxisTitle(QwtPlot::yLeft, yText);
00200
00201 QwtText xText("Time (ms)");
00202 xText.setFont(*axisTitleFont);
00203 tempPlot->setAxisTitle(QwtPlot::xBottom, xText);
00204
00205
00206 Background *bg = new Background();
00207 bg->attach(tempPlot);
00208
00209
00210 QwtPlotCurve *tempCurve = new QwtPlotCurve("Curve 1");
00211 QColor redColor(255, 0, 0);
00212 QBrush tmpBrush(redColor, Qt::Dense4Pattern);
00213 tempCurve->setBrush(tmpBrush);
00214 QPen tmpPen(redColor);
00215 tempCurve->setPen(tmpPen);
00216
00217
00218 MonitorDataset* tempData = new MonitorDataset(DEFAULT_MONITOR_DATASET_SIZE, newGraph.rangeLow, newGraph.rangeHigh);
00219
00220
00221 tempCurve->setData(*tempData);
00222
00223
00224 tempCurve->attach(tempPlot);
00225
00226
00227 tempPlot->replot();
00228
00229
00230 tempPlot->show();
00231
00232
00233 dataVector.push_back(tempData);
00234
00235
00236 plotVector.push_back(tempPlot);
00237
00238
00239 SpikeStreamMainWindow::spikeStreamApplication->unlock();
00240 }
00241
00242
00243
00244
00245 void MonitorDataPlotter::closeDialog(bool stopMon){
00246
00247
00248 if(stopMon)
00249 stopMonitoring();
00250
00251
00252 this->accept();
00253 }
00254
00255
00256
00257 void MonitorDataPlotter::loadingComplete(){
00258 #ifdef GRAPH_LOAD_DEBUG
00259 cout<<"MonitorDataPlotter: Graph loading complete."<<endl;
00260 #endif//GRAPH_LOAD_DEBUG
00261
00262 loadingLabel->hide();
00263 }
00264
00265
00266
00267 void MonitorDataPlotter::plotData(double time, const double* dataArray, int arrayLength){
00268
00269 SpikeStreamMainWindow::spikeStreamApplication->lock();
00270
00271
00272 if((unsigned int)arrayLength != plotVector.size()){
00273 QMessageBox::critical(this, "Monitor Error", "Data and graphs do not match!");
00274 return;
00275 }
00276
00277
00278 for(int i=0; i<arrayLength; ++i){
00279 dataVector[i]->addPoint(time, dataArray[i]);
00280
00281
00282 QwtDoubleRect* bndRect = dataVector[i]->boundingRectRef();
00283 plotVector[i]->setAxisScale(QwtPlot::xBottom, bndRect->left(), bndRect->left() + bndRect->width());
00284
00285
00286 plotVector[i]->replot();
00287 }
00288
00289
00290 SpikeStreamMainWindow::spikeStreamApplication->unlock();
00291 }
00292
00293
00294
00295 bool MonitorDataPlotter::showDialog(){
00296 if(parseError){
00297 QMessageBox::critical( 0, "Monitor Error", "Dialog cannot be shown if it has generated a parsing error");
00298 return false;
00299 }
00300
00301 bool restartOk = true;
00302
00303
00304 SpikeStreamMainWindow::spikeStreamApplication->lock();
00305
00306
00307 if(neuronMonitoring){
00308 if(!((SimulationWidget*)simulationWidget)->getSimulationManager()->startNeuronMonitoring(neuronGrpID, neuronID, true)){
00309 cerr<<"MonitorDataPlotter: ERROR RESTARTING NEURON MONITORING FOR NEURON GROUP "<<neuronGrpID<<" AND NEURON "<<neuronID<<endl;
00310 restartOk = false;
00311 }
00312 }
00313 else{
00314 if(!((SimulationWidget*)simulationWidget)->getSimulationManager()->startSynapseMonitoring(neuronGrpID, fromNeuronID, toNeuronID, true)){
00315 cerr<<"MonitorDataPlotter: ERROR RESTARTING SYNAPSE MONITORING FOR NEURON GROUP "<<neuronGrpID<<" FROM NEURON "<<fromNeuronID<<" TO "<<toNeuronID<<endl;
00316 restartOk = false;
00317 }
00318 }
00319
00320
00321 SpikeStreamMainWindow::spikeStreamApplication->unlock();
00322
00323
00324 this->show();
00325
00326
00327 return restartOk;
00328 }
00329
00330
00331
00332
00333 void MonitorDataPlotter::setUpGraphs(const char* charArray){
00334
00335 SpikeStreamMainWindow::spikeStreamApplication->lock();
00336
00337 #ifdef GRAPH_LOAD_DEBUG
00338 cout<<"MonitorDataPlotter: Parsing XML: "<<charArray<<endl;
00339 #endif//GRAPH_LOAD_DEBUG
00340
00341 QString xmlString(charArray);
00342 try{
00343 QXmlInputSource xmlInput;
00344 xmlInput.setData(xmlString);
00345 MonitorXmlHandler monXmlHandler(this);
00346 QXmlSimpleReader reader;
00347 reader.setContentHandler(&monXmlHandler);
00348 reader.setErrorHandler(&monXmlHandler);
00349 reader.parse(xmlInput);
00350 if(monXmlHandler.getParseError()){
00351
00352 cout<<"MonitorDataPlotter: ERROR OCCURRED DURING PARSING \""<<monXmlHandler.getParseErrorString()<<"\""<<endl;
00353 QString errorString = "Error encountered whilst parsing XML monitor description: \"";
00354 errorString += monXmlHandler.getParseErrorString();
00355 errorString += "\"";
00356 QMessageBox::critical( 0, "Monitor Error", errorString);
00357
00358
00359 parseError = true;
00360
00361
00362 stopMonitoring();
00363
00364
00365 this->accept();
00366 }
00367 }
00368 catch (std::exception& er) {
00369
00370 cerr<<"MonitorDataPlotter: EXCEPTION \""<<er.what()<<"\""<<endl;
00371 QString errorString = "Exception thrown parsing XML monitor description: \"";
00372 errorString += er.what();
00373 errorString += "\"";
00374 QMessageBox::critical( 0, "Monitor Error", errorString);
00375
00376
00377 parseError = true;
00378
00379
00380 stopMonitoring();
00381
00382
00383 this->accept();
00384 }
00385
00386
00387 SpikeStreamMainWindow::spikeStreamApplication->unlock();
00388
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398 void MonitorDataPlotter::closeEvent ( QCloseEvent*){
00399
00400
00401 stopMonitoring();
00402
00403
00404 this->accept();
00405 }
00406
00407
00408
00409
00410
00411
00412
00413 void MonitorDataPlotter::stopMonitoring(){
00414
00415
00416 SpikeStreamMainWindow::spikeStreamApplication->lock();
00417
00418
00419 if(neuronMonitoring)
00420 ((SimulationWidget*)simulationWidget)->getSimulationManager()->stopNeuronMonitoring(neuronGrpID, neuronID);
00421 else
00422 ((SimulationWidget*)simulationWidget)->getSimulationManager()->stopSynapseMonitoring(neuronGrpID, fromNeuronID, toNeuronID);
00423
00424
00425 SpikeStreamMainWindow::spikeStreamApplication->unlock();
00426 }
00427
00428