SpikeStream Nemo Plugin
0.2
|
00001 //SpikeStream includes 00002 #include "DeviceLoaderWidget.h" 00003 #include "ExperimentLoaderWidget.h" 00004 #include "Globals.h" 00005 #include "GlobalVariables.h" 00006 #include "NemoParametersDialog.h" 00007 #include "NemoWidget.h" 00008 #include "NeuronParametersDialog.h" 00009 #include "NeuronGroupSelectionDialog.h" 00010 #include "Pattern.h" 00011 #include "PatternManager.h" 00012 #include "SpikeStreamSimulationException.h" 00013 #include "SynapseParametersDialog.h" 00014 #include "Util.h" 00015 using namespace spikestream; 00016 00017 //Qt includes 00018 #include <QButtonGroup> 00019 #include <QDebug> 00020 #include <QFileDialog> 00021 #include <QLayout> 00022 #include <QMessageBox> 00023 #include <QMutexLocker> 00024 00026 #define LOAD_PATTERN_STRING "Load Pattern" 00027 00028 #define MONITOR_NEURONS_OFF 0 00029 #define MONITOR_NEURONS_FIRING 1 00030 #define MONITOR_NEURONS_MEMBRANE 2 00031 00032 00033 //Functions for dynamic library loading 00034 extern "C" { 00036 QWidget* getClass(){ 00037 return new NemoWidget(); 00038 } 00039 00041 QString getName(){ 00042 return QString("NeMo CUDA Simulator"); 00043 } 00044 } 00045 00046 00048 NemoWidget::NemoWidget(QWidget* parent) : QWidget(parent) { 00049 //Register types to enable signals and slots to work 00050 qRegisterMetaType< QList<unsigned> >("QList<unsigned>"); 00051 qRegisterMetaType< QHash<unsigned, float> >("QHash<unsigned, float>"); 00052 00053 //Create colours to be used for membrane potential 00054 createMembranePotentialColors(); 00055 00056 //Create layout for the entire widget 00057 QVBoxLayout* mainVBox = new QVBoxLayout(this); 00058 mainGroupBox = new QGroupBox("Nemo CUDA Simulator", this); 00059 controlsWidget = new QWidget(); 00060 controlsWidget->setEnabled(false); 00061 QVBoxLayout* controlsVBox = new QVBoxLayout(controlsWidget); 00062 00063 //Add load, unload and parameters buttons 00064 loadButton = new QPushButton("Load"); 00065 connect(loadButton, SIGNAL(clicked()), this, SLOT(loadSimulation())); 00066 unloadButton = new QPushButton("Unload"); 00067 connect(unloadButton, SIGNAL(clicked()), this, SLOT(unloadSimulation())); 00068 unloadButton->setEnabled(false); 00069 neuronParametersButton = new QPushButton(" Neuron Parameters "); 00070 connect(neuronParametersButton, SIGNAL(clicked()), this, SLOT(setNeuronParameters())); 00071 synapseParametersButton = new QPushButton(" Synapse Parameters "); 00072 connect(synapseParametersButton, SIGNAL(clicked()), this, SLOT(setSynapseParameters())); 00073 nemoParametersButton = new QPushButton(" NeMo Parameters "); 00074 connect(nemoParametersButton, SIGNAL(clicked()), this, SLOT(setNemoParameters())); 00075 QHBoxLayout* loadLayout = new QHBoxLayout(); 00076 loadLayout->addWidget(loadButton); 00077 loadLayout->addWidget(unloadButton); 00078 loadLayout->addWidget(neuronParametersButton); 00079 loadLayout->addWidget(synapseParametersButton); 00080 loadLayout->addWidget(nemoParametersButton); 00081 mainVBox->addLayout(loadLayout); 00082 00083 //Add the tool bar 00084 toolBar = getToolBar(); 00085 controlsVBox->addWidget(toolBar); 00086 00087 //Group box for monitoring controls 00088 monitorGroupBox = new QGroupBox("Monitor", controlsWidget); 00089 QVBoxLayout* monitorVBox = new QVBoxLayout(); 00090 00091 //Add widget to control live monitoring of neurons 00092 QHBoxLayout* monitorNeuronsBox = new QHBoxLayout(); 00093 monitorNeuronsBox->addWidget(new QLabel("Monitor neurons: ")); 00094 QButtonGroup* monitorNeuronsButtonGroup = new QButtonGroup(); 00095 connect(monitorNeuronsButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(monitorNeuronsStateChanged(int))); 00096 noMonitorNeuronsButton = new QRadioButton("Off"); 00097 noMonitorNeuronsButton->setChecked(true); 00098 monitorNeuronsButtonGroup->addButton(noMonitorNeuronsButton, MONITOR_NEURONS_OFF); 00099 monitorNeuronsBox->addWidget(noMonitorNeuronsButton); 00100 monitorFiringNeuronsButton = new QRadioButton("Firing"); 00101 monitorNeuronsButtonGroup->addButton(monitorFiringNeuronsButton, MONITOR_NEURONS_FIRING); 00102 monitorNeuronsBox->addWidget(monitorFiringNeuronsButton); 00103 rasterButton = new QPushButton("Raster"); 00104 connect(rasterButton, SIGNAL(clicked()), this, SLOT(rasterButtonClicked())); 00105 rasterButton->setMaximumSize(60,20); 00106 rasterButton->setEnabled(false); 00107 monitorNeuronsBox->addWidget(rasterButton); 00108 monitorMemPotNeuronsButton = new QRadioButton("Membrane potential"); 00109 monitorNeuronsButtonGroup->addButton(monitorMemPotNeuronsButton, MONITOR_NEURONS_MEMBRANE); 00110 monitorNeuronsBox->addWidget(monitorMemPotNeuronsButton); 00111 memPotGraphButton = new QPushButton("Graph"); 00112 connect(memPotGraphButton, SIGNAL(clicked()), this, SLOT(memPotGraphButtonClicked())); 00113 memPotGraphButton->setMaximumSize(60,20); 00114 memPotGraphButton->setEnabled(false); 00115 monitorNeuronsBox->addWidget(memPotGraphButton); 00116 monitorNeuronsBox->addStretch(5); 00117 monitorVBox->addLayout(monitorNeuronsBox); 00118 monitorVBox->addSpacing(5); 00119 00120 //Add widgets to monitor, save and reset the weights 00121 QHBoxLayout* saveWeightsBox = new QHBoxLayout(); 00122 monitorWeightsCheckBox = new QCheckBox("Monitor weights"); 00123 connect(monitorWeightsCheckBox, SIGNAL(clicked(bool)), this, SLOT(setMonitorWeights(bool))); 00124 saveWeightsBox->addWidget(monitorWeightsCheckBox); 00125 /* resetWeightsButton = new QPushButton("Reset Weights"); 00126 connect(resetWeightsButton, SIGNAL(clicked()), this, SLOT(resetWeights())); 00127 saveWeightsBox->addWidget(resetWeightsButton);*/ 00128 saveWeightsButton = new QPushButton("Save Weights"); 00129 connect(saveWeightsButton, SIGNAL(clicked()), this, SLOT(saveWeights())); 00130 saveWeightsBox->addWidget(saveWeightsButton); 00131 saveWeightsBox->addStretch(5); 00132 monitorVBox->addLayout(saveWeightsBox); 00133 00134 //Add widgets to control archiving 00135 archiveCheckBox = new QCheckBox("Archive."); 00136 connect(archiveCheckBox, SIGNAL(stateChanged(int)), this, SLOT(archiveStateChanged(int))); 00137 archiveDescriptionEdit = new QLineEdit("Undescribed"); 00138 archiveDescriptionEdit->setEnabled(false); 00139 setArchiveDescriptionButton = new QPushButton("Set Description"); 00140 setArchiveDescriptionButton->setEnabled(false); 00141 connect(setArchiveDescriptionButton, SIGNAL(clicked()), this, SLOT(setArchiveDescription())); 00142 QHBoxLayout* archiveLayout = new QHBoxLayout(); 00143 archiveLayout->addWidget(archiveCheckBox); 00144 archiveLayout->addWidget(archiveDescriptionEdit); 00145 archiveLayout->addWidget(setArchiveDescriptionButton); 00146 monitorVBox->addLayout(archiveLayout); 00147 00148 //Add monitor group box to layout 00149 monitorGroupBox->setLayout(monitorVBox); 00150 controlsVBox->addWidget(monitorGroupBox); 00151 00152 //Group box for injection controls 00153 injectGroupBox = new QGroupBox("Inject", controlsWidget); 00154 QVBoxLayout* injectVBox = new QVBoxLayout(); 00155 00156 00157 //Add widgets to inject noise into specified layers 00158 QHBoxLayout* injectNoiseBox = new QHBoxLayout(); 00159 injectNoiseNeuronGroupCombo = new QComboBox(); 00160 injectNoiseNeuronGroupCombo->setMinimumSize(200, 20); 00161 injectNoiseBox->addWidget(injectNoiseNeuronGroupCombo); 00162 injectNoisePercentCombo = new QComboBox(); 00163 injectNoisePercentCombo->addItem("0.1 %"); 00164 injectNoisePercentCombo->addItem("1 %"); 00165 for(int i=10; i<=100; i += 10) 00166 injectNoisePercentCombo->addItem(QString::number(i) + " %"); 00167 injectNoisePercentCombo->setMinimumSize(60, 20); 00168 injectNoiseBox->addWidget(injectNoisePercentCombo); 00169 00170 injectNoiseCurrentCombo = new QComboBox(); 00171 injectNoiseCurrentCombo->addItem("Fire"); 00172 injectNoiseCurrentCombo->addItem("1"); 00173 for(int i=10; i<=100; i += 10) 00174 injectNoiseCurrentCombo->addItem(QString::number(i)); 00175 injectNoiseCurrentCombo->setMinimumSize(60, 20); 00176 injectNoiseBox->addWidget(injectNoiseCurrentCombo); 00177 00178 injectNoiseButton = new QPushButton("Inject Noise"); 00179 injectNoiseButton->setMinimumHeight(20); 00180 connect(injectNoiseButton, SIGNAL(clicked()), this, SLOT(injectNoiseButtonClicked())); 00181 injectNoiseBox->addWidget(injectNoiseButton); 00182 sustainNoiseChkBox = new QCheckBox("Sustain"); 00183 connect(sustainNoiseChkBox, SIGNAL(clicked(bool)), this, SLOT(sustainNoiseChanged(bool))); 00184 injectNoiseBox->addWidget(sustainNoiseChkBox); 00185 injectNoiseBox->addStretch(5); 00186 injectVBox->addSpacing(5); 00187 injectVBox->addLayout(injectNoiseBox); 00188 00189 //Add widgets to enable injection of patterns 00190 QHBoxLayout* injectPatternBox = new QHBoxLayout(); 00191 injectPatternNeurGrpCombo = new QComboBox(); 00192 injectPatternNeurGrpCombo->setMinimumSize(200, 20); 00193 injectPatternBox->addWidget(injectPatternNeurGrpCombo); 00194 patternCombo = new QComboBox(); 00195 patternCombo->setMinimumSize(200, 20); 00196 patternCombo->addItem(""); 00197 patternCombo->addItem(LOAD_PATTERN_STRING); 00198 connect(patternCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(loadPattern(QString))); 00199 patternCurrentCombo = new QComboBox(); 00200 fillPatternCurrentCombo(); 00201 injectPatternBox->addWidget(patternCurrentCombo); 00202 injectPatternBox->addWidget(patternCombo); 00203 injectPatternButton = new QPushButton("Inject Pattern"); 00204 injectPatternButton->setEnabled(false); 00205 injectPatternButton->setMinimumHeight(22); 00206 connect(injectPatternButton, SIGNAL(clicked()), this, SLOT(injectPatternButtonClicked())); 00207 injectPatternBox->addWidget(injectPatternButton); 00208 sustainPatternChkBox = new QCheckBox("Sustain"); 00209 sustainPatternChkBox->setEnabled(false); 00210 connect(sustainPatternChkBox, SIGNAL(clicked(bool)), this, SLOT(sustainPatternChanged(bool))); 00211 injectPatternBox->addWidget(sustainPatternChkBox); 00212 injectVBox->addSpacing(5); 00213 injectVBox->addLayout(injectPatternBox); 00214 00215 //Add inject group box to layout 00216 injectGroupBox->setLayout(injectVBox); 00217 controlsVBox->addWidget(injectGroupBox); 00218 00219 //Group box for plugins, such as experiments and devices 00220 QGroupBox* pluginsGroupBox = new QGroupBox("Plugins", controlsWidget); 00221 QVBoxLayout* pluginsVBox = new QVBoxLayout(); 00222 QTabWidget* pluginsTabWidget = new QTabWidget(); 00223 00224 //Add widget that loads devices 00225 DeviceLoaderWidget* deviceLoaderWidget = new DeviceLoaderWidget(Globals::getSpikeStreamRoot() + "/plugins/simulation/nemodevices"); 00226 deviceLoaderWidget->setMinimumSize(600, 200); 00227 pluginsTabWidget->addTab(deviceLoaderWidget, "Devices"); 00228 00229 //Add widget that loads experiments 00230 ExperimentLoaderWidget* exptLoaderWidget = new ExperimentLoaderWidget(Globals::getSpikeStreamRoot() + "/plugins/simulation/nemoexperiments"); 00231 exptLoaderWidget->setMinimumSize(600, 200); 00232 pluginsTabWidget->addTab(exptLoaderWidget, "Experiments"); 00233 00234 //Add experiment group box to layout 00235 pluginsVBox->addWidget(pluginsTabWidget); 00236 pluginsGroupBox->setLayout(pluginsVBox); 00237 controlsVBox->addWidget(pluginsGroupBox); 00238 00239 //Put layout into enclosing box 00240 mainVBox->addWidget(controlsWidget); 00241 mainGroupBox->setLayout(mainVBox); 00242 this->setMinimumSize(800, 800); 00243 00244 //Create wrapper for Nemo library 00245 nemoWrapper = new NemoWrapper(); 00246 connect(nemoWrapper, SIGNAL(finished()), this, SLOT(nemoWrapperFinished())); 00247 connect(nemoWrapper, SIGNAL(progress(int,int)), this, SLOT(updateProgress(int, int)), Qt::QueuedConnection); 00248 connect(nemoWrapper, SIGNAL(simulationStopped()), this, SLOT(simulationStopped()), Qt::QueuedConnection); 00249 connect(nemoWrapper, SIGNAL(timeStepChanged(unsigned)), this, SLOT(updateTimeStep(unsigned)), Qt::QueuedConnection); 00250 connect(nemoWrapper, SIGNAL(timeStepChanged(unsigned, const QList<unsigned>&)), this, SLOT(updateTimeStep(unsigned, const QList<unsigned>&)), Qt::QueuedConnection); 00251 connect(nemoWrapper, SIGNAL(timeStepChanged(unsigned, const QHash<unsigned, float>&)), this, SLOT(updateTimeStep(unsigned, const QHash<unsigned, float>&)), Qt::QueuedConnection); 00252 00253 //Pass device managers to NeMo wrapper 00254 QList<AbstractDeviceWidget*> deviceWidgetList = deviceLoaderWidget->getAbstractDeviceWidgets(); 00255 foreach(AbstractDeviceWidget* tmpDevWidget, deviceWidgetList){ 00256 nemoWrapper->addDeviceManager(tmpDevWidget->getDeviceManager()); 00257 } 00258 00259 //Set up link between experiment widgets and NeMo wrapper and signals/slots 00260 QList<AbstractExperimentWidget*> exptWidgetList = exptLoaderWidget->getAbstractExperimentWidgets(); 00261 foreach(AbstractExperimentWidget* tmpExptWidget, exptWidgetList){ 00262 tmpExptWidget->setWrapper(nemoWrapper); 00263 connect(tmpExptWidget, SIGNAL(experimentStarted()), this, SLOT(experimentStarted())); 00264 connect(tmpExptWidget, SIGNAL(experimentEnded()), this, SLOT(experimentEnded())); 00265 } 00266 00267 //Listen for network changes 00268 connect(Globals::getEventRouter(), SIGNAL(networkChangedSignal()), this, SLOT(networkChanged())); 00269 00270 //Listen for simulation control events 00271 connect(Globals::getEventRouter(), SIGNAL(startStopSimulationSignal()), this, SLOT(startStopSimulation())); 00272 connect(Globals::getEventRouter(), SIGNAL(stepSimulationSignal()), this, SLOT(stepSimulation())); 00273 00274 //Set initial state of tool bar 00275 checkWidgetEnabled(); 00276 00277 //Initialise variables 00278 progressDialog = NULL; 00279 rasterDialogCtr = 0; 00280 } 00281 00282 00284 NemoWidget::~NemoWidget(){ 00285 delete nemoWrapper; 00286 for(QHash<int, RGBColor*>::iterator iter = heatColorMap.begin(); iter != heatColorMap.end(); ++iter) 00287 delete iter.value(); 00288 heatColorMap.clear(); 00289 } 00290 00291 00292 /*----------------------------------------------------------*/ 00293 /*------ PRIVATE SLOTS ------*/ 00294 /*----------------------------------------------------------*/ 00295 00297 void NemoWidget::archiveStateChanged(int state){ 00298 if(state == Qt::Checked){ 00299 archiveDescriptionEdit->setEnabled(true); 00300 setArchiveDescriptionButton->setEnabled(true); 00301 if(archiveDescriptionEdit->text().isEmpty()) 00302 archiveDescriptionEdit->setText("Undescribed"); 00303 nemoWrapper->setArchiveMode(true, archiveDescriptionEdit->text()); 00304 } 00305 else{ 00306 archiveDescriptionEdit->setEnabled(false); 00307 setArchiveDescriptionButton->setEnabled(false); 00308 nemoWrapper->setArchiveMode(false); 00309 } 00310 } 00311 00312 00316 void NemoWidget::checkLoadingProgress(){ 00317 //Check for errors during loading 00318 if(nemoWrapper->isError()){ 00319 loadingTimer->stop(); 00320 progressDialog->setValue(progressDialog->maximum()); 00321 delete progressDialog; 00322 progressDialog = NULL; 00323 qCritical()<<"Error occurred loading simulation: '"<<nemoWrapper->getErrorMessage()<<"'."; 00324 return; 00325 } 00326 00327 //Check for cancelation - stop timer and abort operation 00328 else if(progressDialog->wasCanceled()){ 00329 loadingTimer->stop(); 00330 nemoWrapper->cancelLoading(); 00331 delete progressDialog; 00332 progressDialog = NULL; 00333 return; 00334 } 00335 00336 //If simulation has not been loaded return with loading timer still running 00337 else if(!nemoWrapper->isSimulationLoaded()){ 00338 return; 00339 } 00340 00341 else if (updatingProgress){ 00342 return; 00343 } 00344 00345 //If we have reached this point, loading is complete 00346 loadingTimer->stop(); 00347 progressDialog->setValue(progressDialog->maximum()); 00348 delete progressDialog; 00349 progressDialog = NULL; 00350 00351 //Adjust buttons 00352 loadButton->setEnabled(false); 00353 unloadButton->setEnabled(true); 00354 synapseParametersButton->setEnabled(false); 00355 nemoParametersButton->setEnabled(false); 00356 controlsWidget->setEnabled(true); 00357 playAction->setEnabled(true); 00358 stopAction->setEnabled(false); 00359 stepAction->setEnabled(true); 00360 monitorWeightsCheckBox->setChecked(nemoWrapper->isMonitorWeights()); 00361 archiveCheckBox->setChecked(false);//Single archive associated with each simulation run 00362 00363 //Cannot save weights or archive if the network is not fully saved in the database 00364 if(!Globals::getNetwork()->isSaved()){ 00365 archiveCheckBox->setEnabled(false); 00366 setArchiveDescriptionButton->setEnabled(false); 00367 archiveDescriptionEdit->setEnabled(false); 00368 } 00369 else{ 00370 archiveCheckBox->setEnabled(true); 00371 setArchiveDescriptionButton->setEnabled(true); 00372 archiveDescriptionEdit->setEnabled(true); 00373 } 00374 00375 //Set nemo wrapper as the simulation in global scope 00376 Globals::setSimulation(nemoWrapper); 00377 } 00378 00379 00381 void NemoWidget::checkResetWeightsProgress(){ 00382 //Check for errors during resetting weights 00383 if(nemoWrapper->isError()){ 00384 heavyTaskTimer->stop(); 00385 progressDialog->setValue(progressDialog->maximum()); 00386 delete progressDialog; 00387 progressDialog = NULL; 00388 qCritical()<<"Error occurred resetting of weights: '"<<nemoWrapper->getErrorMessage()<<"'."; 00389 return; 00390 } 00391 00392 //Check for cancelation - stop timer and abort operation 00393 else if(progressDialog->wasCanceled()){ 00394 heavyTaskTimer->stop(); 00395 nemoWrapper->cancelResetWeights(); 00396 delete progressDialog; 00397 progressDialog = NULL; 00398 return; 00399 } 00400 00401 //If save weights is not complete return with timer running 00402 else if(!nemoWrapper->isWeightsReset()){ 00403 return; 00404 } 00405 00406 else if (updatingProgress){ 00407 return; 00408 } 00409 00410 //If we have reached this point, loading is complete 00411 heavyTaskTimer->stop(); 00412 progressDialog->setValue(progressDialog->maximum()); 00413 delete progressDialog; 00414 progressDialog = NULL; 00415 } 00416 00417 00419 void NemoWidget::checkSaveWeightsProgress(){ 00420 //Check for errors during loading 00421 if(nemoWrapper->isError()){ 00422 heavyTaskTimer->stop(); 00423 progressDialog->setValue(progressDialog->maximum()); 00424 delete progressDialog; 00425 progressDialog = NULL; 00426 qCritical()<<"Error occurred saving of weights: '"<<nemoWrapper->getErrorMessage()<<"'."; 00427 return; 00428 } 00429 00430 //Check for cancelation - stop timer and abort operation 00431 else if(progressDialog->wasCanceled()){ 00432 heavyTaskTimer->stop(); 00433 nemoWrapper->cancelSaveWeights(); 00434 delete progressDialog; 00435 progressDialog = NULL; 00436 return; 00437 } 00438 00439 //If simulation has not been loaded return with loading timer still running 00440 else if(!nemoWrapper->isWeightsSaved()){ 00441 return; 00442 } 00443 00444 //Make sure that progress dialog is not being redrawn 00445 else if (updatingProgress){ 00446 return; 00447 } 00448 00449 //If we have reached this point, loading is complete 00450 heavyTaskTimer->stop(); 00451 progressDialog->setValue(progressDialog->maximum()); 00452 delete progressDialog; 00453 progressDialog = NULL; 00454 } 00455 00456 00459 void NemoWidget::deleteMembranePotentialGraphDialog(int){ 00460 unsigned tmpID = sender()->objectName().toUInt(); 00461 qDebug()<<"Deleting Membrane potential graph dialog with ID: "<<tmpID; 00462 if(!memPotGraphDialogMap.contains(tmpID)){ 00463 qCritical()<<"Raster dialog not found: ID="<<tmpID; 00464 return; 00465 } 00466 memPotGraphDialogMap.remove(tmpID); 00467 } 00468 00469 00472 void NemoWidget::deleteRasterPlotDialog(int){ 00473 unsigned tmpID = sender()->objectName().toUInt(); 00474 qDebug()<<"Deleting Raster plot dialog with ID: "<<tmpID; 00475 if(!rasterDialogMap.contains(tmpID)) 00476 throw SpikeStreamException("Raster dialog not found: ID=" + QString::number(tmpID)); 00477 //delete rasterDialogMap[tmpID]; 00478 rasterDialogMap.remove(tmpID); 00479 } 00480 00481 00483 void NemoWidget::experimentEnded(){ 00484 toolBar->setEnabled(true); 00485 monitorGroupBox->setEnabled(true); 00486 injectGroupBox->setEnabled(true); 00487 } 00488 00489 00491 void NemoWidget::experimentStarted(){ 00492 toolBar->setEnabled(false); 00493 monitorGroupBox->setEnabled(false); 00494 injectGroupBox->setEnabled(false); 00495 } 00496 00497 00500 void NemoWidget::injectNoiseButtonClicked(){ 00501 setInjectNoise(false); 00502 } 00503 00504 00507 void NemoWidget::injectPatternButtonClicked(){ 00508 setInjectionPattern(false); 00509 } 00510 00511 00514 void NemoWidget::loadPattern(QString comboStr){ 00515 //Return if we are setting the pattern to another pattern. 00516 if(comboStr != LOAD_PATTERN_STRING){ 00517 return; 00518 } 00519 00520 //Reset pattern combo 00521 patternCombo->setCurrentIndex(0); 00522 00523 //Select file containing new pattern. 00524 QString filePath = getFilePath("*.pat"); 00525 if(filePath.isEmpty()) 00526 return; 00527 if(!QFile::exists(filePath)){ 00528 qCritical()<<"Selected file '"<<filePath<<"' does not exist."; 00529 return; 00530 } 00531 00532 try{ 00533 //Load up the new pattern 00534 Pattern newPattern; 00535 PatternManager::load(filePath, newPattern); 00536 00537 //Add name to combo if it does not already exist 00538 if(!patternMap.contains(filePath)){ 00539 patternCombo->insertItem(patternCombo->count() - 1, newPattern.getName()); 00540 } 00541 00542 //Replace pattern stored for this name with new pattern or add it if it doesn't exist. 00543 patternMap[filePath] = newPattern; 00544 00545 //Set combo to display loaded item 00546 if(patternCombo->itemText(0) == "") 00547 patternCombo->removeItem(0); 00548 patternCombo->setCurrentIndex(patternCombo->count() - 2); 00549 00550 //Enable injection and sustain buttons 00551 injectPatternButton->setEnabled(true); 00552 sustainPatternChkBox->setEnabled(true); 00553 } 00554 catch(SpikeStreamException* ex){ 00555 qCritical()<<ex->getMessage(); 00556 } 00557 } 00558 00559 00561 void NemoWidget::loadSimulation(){ 00562 //Run some checks 00563 if(!Globals::networkLoaded()){ 00564 qCritical()<<"Cannot load simulation: no network loaded."; 00565 return; 00566 } 00567 if(nemoWrapper->isRunning()){ 00568 qCritical()<<"Nemo wrapper is already running - cannot load simulation."; 00569 return; 00570 } 00571 if(nemoWrapper->isSimulationLoaded()){ 00572 qCritical()<<"Simulation is already loaded - you must unload the current simulation before loading another."; 00573 return; 00574 } 00575 00576 //Load the current neuron groups into control widgets 00577 loadNeuronGroups(); 00578 00579 try{ 00580 //Store the current neuron colour for monitoring 00581 neuronColor = Globals::getNetworkDisplay()->getSimulationFiringNeuronColor(); 00582 00583 //Start loading of simulation 00584 taskCancelled = false; 00585 progressDialog = new QProgressDialog("Loading simulation", "Cancel", 0, 100, this, Qt::CustomizeWindowHint); 00586 progressDialog->setWindowModality(Qt::WindowModal); 00587 progressDialog->show(); 00588 updatingProgress = false; 00589 nemoWrapper->start();//Load carried out by run method 00590 00591 //Wait for loading to finish and update progress dialog 00592 loadingTimer = new QTimer(this); 00593 connect(loadingTimer, SIGNAL(timeout()), this, SLOT(checkLoadingProgress())); 00594 loadingTimer->start(200); 00595 } 00596 catch(SpikeStreamException& ex){ 00597 qCritical()<<ex.getMessage(); 00598 } 00599 } 00600 00601 00602 00605 void NemoWidget::memPotGraphButtonClicked(){ 00606 //Get ID of current neuron 00607 neurid_t neurID = Globals::getNetworkDisplay()->getSingleNeuronID(); 00608 if(neurID < START_NEURON_ID){ 00609 qCritical()<<"No neuron selected. You must select a neuron to plot a membrane potential graph."; 00610 return; 00611 } 00612 00613 //Do nothing if we are already monitoring this neuron 00614 if(memPotGraphDialogMap.contains(neurID)){ 00615 qDebug()<<"Already monitoring this neuron"; 00616 return; 00617 } 00618 00619 try{ 00620 //Create raster dialog 00621 MembranePotentialGraphDialog* memPotDlg = new MembranePotentialGraphDialog(neurID, this); 00622 memPotDlg->setObjectName(QString::number(neurID)); 00623 connect(memPotDlg, SIGNAL(finished(int)), this, SLOT(deleteMembranePotentialGraphDialog(int))); 00624 memPotDlg->show(); 00625 00626 //Store details so that we can update it 00627 memPotGraphDialogMap[neurID] = memPotDlg; 00628 } 00629 catch(SpikeStreamException& ex){ 00630 qCritical()<<ex.getMessage(); 00631 } 00632 } 00633 00634 00635 00637 void NemoWidget::monitorChanged(int state){ 00638 try{ 00639 if(state == Qt::Checked){ 00640 nemoWrapper->setMonitor(true); 00641 if(nemoWrapper->isSimulationLoaded()){ 00642 timeStepLabel->setText(QString::number(nemoWrapper->getTimeStep())); 00643 } 00644 noMonitorNeuronsButton->setEnabled(true); 00645 monitorFiringNeuronsButton->setEnabled(true); 00646 monitorMemPotNeuronsButton->setEnabled(true); 00647 monitorWeightsCheckBox->setEnabled(true); 00648 } 00649 else{ 00650 nemoWrapper->setMonitor(false); 00651 noMonitorNeuronsButton->setEnabled(false); 00652 monitorFiringNeuronsButton->setEnabled(false); 00653 monitorMemPotNeuronsButton->setEnabled(false); 00654 monitorWeightsCheckBox->setEnabled(false); 00655 } 00656 } 00657 catch(SpikeStreamException& ex){ 00658 qCritical()<<ex.getMessage(); 00659 } 00660 } 00661 00662 00664 void NemoWidget::monitorNeuronsStateChanged(int monitorType){ 00665 try{ 00666 //No monitoring at all 00667 if(monitorType == MONITOR_NEURONS_OFF){ 00668 nemoWrapper->setMonitorNeurons(false, false); 00669 rasterButton->setEnabled(false); 00670 memPotGraphButton->setEnabled(false); 00671 } 00672 //Monitoring firing neurons 00673 else if(monitorType == MONITOR_NEURONS_FIRING){ 00674 nemoWrapper->setMonitorNeurons(true, false); 00675 rasterButton->setEnabled(true); 00676 memPotGraphButton->setEnabled(false); 00677 } 00678 //Monitoring membrane potential 00679 else if(monitorType == MONITOR_NEURONS_MEMBRANE){ 00680 nemoWrapper->setMonitorNeurons(false, true); 00681 rasterButton->setEnabled(false); 00682 memPotGraphButton->setEnabled(true); 00683 } 00684 //Unrecognized value 00685 else{ 00686 qCritical()<<"Monitor neuron type not recognized: "<<monitorType; 00687 return; 00688 } 00689 00690 //Clear current highlights 00691 QHash<unsigned int, RGBColor*>* newHighlightMap = new QHash<unsigned int, RGBColor*>(); 00692 Globals::getNetworkDisplay()->setNeuronColorMap(newHighlightMap); 00693 } 00694 catch(SpikeStreamException& ex){ 00695 qCritical()<<ex.getMessage(); 00696 } 00697 } 00698 00699 00702 void NemoWidget::nemoWrapperFinished(){ 00703 checkForErrors(); 00704 unloadSimulation(false); 00705 } 00706 00707 00710 void NemoWidget::networkChanged(){ 00711 if(nemoWrapper->isSimulationRunning()) 00712 qCritical()<<"Network should not be changed while simulation is running"; 00713 00714 //Unload simulation if it is loaded 00715 unloadSimulation(false); 00716 00717 //Fix enabled status of toolbar 00718 checkWidgetEnabled(); 00719 } 00720 00721 00724 void NemoWidget::rasterButtonClicked(){ 00725 //Select neuron groups to monitor 00726 NeuronGroupSelectionDialog selectDlg(Globals::getNetwork(), this); 00727 if(selectDlg.exec() == QDialog::Accepted){ 00728 QList<NeuronGroup*> neurGrpList = selectDlg.getNeuronGroups(); 00729 00730 //Create raster dialog 00731 SpikeRasterDialog* rasterDlg = new SpikeRasterDialog(neurGrpList, this); 00732 rasterDlg->setObjectName(QString::number(rasterDialogCtr)); 00733 connect(rasterDlg, SIGNAL(finished(int)), this, SLOT(deleteRasterPlotDialog(int))); 00734 rasterDlg->show(); 00735 00736 //Store details so that we can update it 00737 rasterDialogMap[rasterDialogCtr] = rasterDlg; 00738 ++rasterDialogCtr; 00739 } 00740 } 00741 00742 00745 void NemoWidget::resetWeights(){ 00746 //Check user wants to save weights. 00747 int response = QMessageBox::warning(this, "Reset Weights?", "Are you sure that you want to reset the weights.\nThis will overwrite the trained weights and cannot be undone.", QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); 00748 if(response != QMessageBox::Ok) 00749 return; 00750 00751 try{ 00752 00753 //Start resetting of weights 00754 updatingProgress = false; 00755 taskCancelled = false; 00756 progressDialog = new QProgressDialog("Resetting weights", "Cancel", 0, 100, this); 00757 progressDialog->setWindowModality(Qt::WindowModal); 00758 progressDialog->setMinimumDuration(1000); 00759 00760 //Instruct wrapper thread to start saving weights 00761 nemoWrapper->resetWeights(); 00762 00763 //Wait for loading to finish and update progress dialog 00764 heavyTaskTimer = new QTimer(this); 00765 connect(heavyTaskTimer, SIGNAL(timeout()), this, SLOT(checkResetWeightsProgress())); 00766 heavyTaskTimer->start(200); 00767 } 00768 catch(SpikeStreamException& ex){ 00769 qCritical()<<ex.getMessage(); 00770 } 00771 } 00772 00775 void NemoWidget::saveWeights(){ 00776 //Check user wants to save weights. 00777 int response = QMessageBox::warning(this, "Save Weights?", "Are you sure that you want to save weights.\nThis will overwrite the current weights in the loaded network.", QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); 00778 if(response != QMessageBox::Ok) 00779 return; 00780 00781 //Double check that network does not have analyses 00782 if(Globals::getAnalysisDao()->networkHasAnalyses(Globals::getNetwork()->getID())){ 00783 qCritical()<<"Network is linked to analyses - weights cannot be saved until analyses are deleted."; 00784 return; 00785 } 00786 00787 try{ 00788 //Start saving of weights 00789 updatingProgress = false; 00790 taskCancelled = false; 00791 progressDialog = new QProgressDialog("Saving weights", "Cancel", 0, 100, this, Qt::CustomizeWindowHint); 00792 progressDialog->setWindowModality(Qt::WindowModal); 00793 progressDialog->setMinimumDuration(0); 00794 progressDialog->setAutoClose(false); 00795 progressDialog->show(); 00796 00797 //Instruct wrapper thread to start saving weights 00798 nemoWrapper->saveWeights(); 00799 00800 //Wait for loading to finish and update progress dialog 00801 heavyTaskTimer = new QTimer(this); 00802 connect(heavyTaskTimer, SIGNAL(timeout()), this, SLOT(checkSaveWeightsProgress())); 00803 heavyTaskTimer->start(200); 00804 } 00805 catch(SpikeStreamException& ex){ 00806 qCritical()<<ex.getMessage(); 00807 } 00808 } 00809 00810 00813 void NemoWidget::setMonitorWeights(bool enable){ 00814 nemoWrapper->setMonitorWeights(enable); 00815 } 00816 00817 00819 void NemoWidget::setArchiveDescription(){ 00820 if(archiveDescriptionEdit->text().isEmpty()) 00821 archiveDescriptionEdit->setText("Undescribed"); 00822 if(nemoWrapper->getArchiveID() == 0){ 00823 qCritical()<<"Attempting to set archive description when no archive is in use by NeMo."; 00824 return; 00825 } 00826 Globals::getArchiveDao()->setArchiveProperties(nemoWrapper->getArchiveID(), archiveDescriptionEdit->text()); 00827 Globals::getEventRouter()->archiveListChangedSlot(); 00828 } 00829 00830 00832 void NemoWidget::setNeuronParameters(){ 00833 NeuronParametersDialog* dialog = new NeuronParametersDialog(this); 00834 dialog->exec(); 00835 delete dialog; 00836 } 00837 00838 00840 void NemoWidget::setNemoParameters(){ 00841 try{ 00842 NemoParametersDialog dialog(nemoWrapper->getNemoConfig(), nemoWrapper->getSTDPFunctionID(), this); 00843 if(dialog.exec() == QDialog::Accepted){ 00844 nemoWrapper->setNemoConfig(dialog.getNemoConfig()); 00845 nemoWrapper->setSTDPFunctionID(dialog.getSTDPFunctionID()); 00846 } 00847 } 00848 catch(SpikeStreamException& ex){ 00849 qCritical()<<ex.getMessage(); 00850 } 00851 } 00852 00853 00855 void NemoWidget::setSynapseParameters(){ 00856 SynapseParametersDialog* dialog = new SynapseParametersDialog(this); 00857 dialog->exec(); 00858 delete dialog; 00859 } 00860 00861 00863 void NemoWidget::simulationStopped(){ 00864 saveWeightsButton->setEnabled(true); 00865 playAction->setEnabled(true); 00866 stopAction->setEnabled(false); 00867 stepAction->setEnabled(true); 00868 unloadButton->setEnabled(true); 00869 neuronParametersButton->setEnabled(true); 00870 } 00871 00872 00875 void NemoWidget::updateTimeStep(unsigned int timeStep){ 00876 timeStepLabel->setText(QString::number(timeStep)); 00877 00878 //Allow simulation to proceed on to next step 00879 nemoWrapper->clearWaitForGraphics(); 00880 } 00881 00882 00885 void NemoWidget::updateTimeStep(unsigned int timeStep, const QList<unsigned>& neuronIDList){ 00886 timeStepLabel->setText(QString::number(timeStep)); 00887 00888 //Fill map with neuron ids 00889 QHash<unsigned int, RGBColor*>* newHighlightMap = new QHash<unsigned int, RGBColor*>(); 00890 QList<unsigned>::const_iterator endList = neuronIDList.end(); 00891 for(QList<unsigned>::const_iterator iter = neuronIDList.begin(); iter != endList; ++iter){ 00892 (*newHighlightMap)[*iter] = neuronColor; 00893 } 00894 00895 //Set highlight map in network display 00896 Globals::getNetworkDisplay()->setNeuronColorMap(newHighlightMap); 00897 00898 //Update spike rasters 00899 for(QHash<unsigned, SpikeRasterDialog*>::iterator iter = rasterDialogMap.begin(); iter != rasterDialogMap.end(); ++iter) 00900 iter.value()->addData(neuronIDList, timeStep); 00901 00902 //Allow simulation to proceed on to next step 00903 nemoWrapper->clearWaitForGraphics(); 00904 } 00905 00906 00909 void NemoWidget::updateTimeStep(unsigned int timeStep, const QHash<unsigned, float>& membranePotentialMap){ 00910 timeStepLabel->setText(QString::number(timeStep)); 00911 00912 //Fill map with appropriate colours depending on membrane potential. 00913 float tmpMemPot = 0.0f; 00914 QHash<unsigned int, RGBColor*>* newHighlightMap = new QHash<unsigned int, RGBColor*>(); 00915 QHash<unsigned, float>::const_iterator endMap = membranePotentialMap.end(); 00916 for(QHash<unsigned, float>::const_iterator iter = membranePotentialMap.begin(); iter != endMap; ++iter){ 00917 //Update 3D display 00918 tmpMemPot = iter.value(); 00919 if(tmpMemPot < -89.0f) 00920 (*newHighlightMap)[iter.key()] = heatColorMap[-1]; 00921 else if(tmpMemPot < -78.0f) 00922 (*newHighlightMap)[iter.key()] = heatColorMap[0]; 00923 else if(tmpMemPot < -67.0f) 00924 (*newHighlightMap)[iter.key()] = heatColorMap[1]; 00925 else if(tmpMemPot < -56.0f) 00926 (*newHighlightMap)[iter.key()] = heatColorMap[2]; 00927 else if(tmpMemPot < -45.0f) 00928 (*newHighlightMap)[iter.key()] = heatColorMap[3]; 00929 else if(tmpMemPot < -34.0f) 00930 (*newHighlightMap)[iter.key()] = heatColorMap[4]; 00931 else if(tmpMemPot < -23.0f) 00932 (*newHighlightMap)[iter.key()] = heatColorMap[5]; 00933 else if(tmpMemPot < -12.0f) 00934 (*newHighlightMap)[iter.key()] = heatColorMap[6]; 00935 else if(tmpMemPot < -1.0f) 00936 (*newHighlightMap)[iter.key()] = heatColorMap[7]; 00937 else if(tmpMemPot < 10.0f) 00938 (*newHighlightMap)[iter.key()] = heatColorMap[8]; 00939 else if(tmpMemPot < 21.0f) 00940 (*newHighlightMap)[iter.key()] = heatColorMap[9]; 00941 else 00942 (*newHighlightMap)[iter.key()] = heatColorMap[10]; 00943 00944 //Update graphs 00945 if(memPotGraphDialogMap.contains(iter.key())){ 00946 memPotGraphDialogMap[iter.key()]->addData(iter.value(), timeStep); 00947 } 00948 } 00949 00950 //Set network display 00951 Globals::getNetworkDisplay()->setNeuronColorMap(newHighlightMap); 00952 00953 //Allow simulation to proceed on to next step 00954 nemoWrapper->clearWaitForGraphics(); 00955 } 00956 00957 00959 void NemoWidget::simulationRateChanged(int){ 00960 if(simulationRateCombo->currentText() == "Max") 00961 nemoWrapper->setFrameRate(0); 00962 else{ 00963 unsigned int frameRate = Util::getUInt(simulationRateCombo->currentText()); 00964 nemoWrapper->setFrameRate(frameRate); 00965 } 00966 } 00967 00968 00970 void NemoWidget::startSimulation(){ 00971 //Do nothing if there is no simulation loaded or if wrapper is busy 00972 if(!nemoWrapper->isSimulationLoaded()){ 00973 return; 00974 } 00975 try{ 00976 nemoWrapper->playSimulation(); 00977 playAction->setEnabled(false); 00978 stopAction->setEnabled(true); 00979 stepAction->setEnabled(false); 00980 unloadButton->setEnabled(false); 00981 neuronParametersButton->setEnabled(false); 00982 saveWeightsButton->setEnabled(false); 00983 } 00984 catch(SpikeStreamException& ex){ 00985 qCritical()<<ex.getMessage(); 00986 } 00987 } 00988 00989 00991 void NemoWidget::startStopSimulation(){ 00992 //Do nothing if there is no simulation loaded or if wrapper is busy 00993 if(!nemoWrapper->isSimulationLoaded()){ 00994 return; 00995 } 00996 if(nemoWrapper->getCurrentTask() == NemoWrapper::NO_TASK_DEFINED) 00997 startSimulation(); 00998 else if(nemoWrapper->getCurrentTask() == NemoWrapper::RUN_SIMULATION_TASK) 00999 stopSimulation(); 01000 } 01001 01002 01004 void NemoWidget::stepSimulation(){ 01005 //Do nothing if there is no simulation loaded or if wrapper is busy 01006 if(!nemoWrapper->isSimulationLoaded() || nemoWrapper->getCurrentTask() != NemoWrapper::NO_TASK_DEFINED){ 01007 return; 01008 } 01009 01010 //Step simulation 01011 try{ 01012 nemoWrapper->stepSimulation(); 01013 } 01014 catch(SpikeStreamException& ex){ 01015 qCritical()<<ex.getMessage(); 01016 } 01017 } 01018 01019 01021 void NemoWidget::stopSimulation(){ 01022 //Do nothing if there is no simulation loaded 01023 if(!nemoWrapper->isSimulationLoaded()){ 01024 return; 01025 } 01026 01027 nemoWrapper->stopSimulation(); 01028 } 01029 01030 01033 void NemoWidget::sustainNoiseChanged(bool enabled){ 01034 if(enabled){ 01035 injectNoiseButton->setEnabled(false); 01036 injectNoisePercentCombo->setEnabled(false); 01037 injectNoiseCurrentCombo->setEnabled(false); 01038 injectNoiseNeuronGroupCombo->setEnabled(false); 01039 setInjectNoise(true); 01040 } 01041 else{ 01042 injectNoiseButton->setEnabled(true); 01043 injectNoisePercentCombo->setEnabled(true); 01044 injectNoiseCurrentCombo->setEnabled(true); 01045 injectNoiseNeuronGroupCombo->setEnabled(true); 01046 01047 //Switch off sustain noise - it will be automatically deleted on next step. 01048 nemoWrapper->setSustainNoise(false); 01049 } 01050 } 01051 01054 void NemoWidget::sustainPatternChanged(bool enabled){ 01055 if(enabled){ 01056 injectPatternButton->setEnabled(false); 01057 injectPatternNeurGrpCombo->setEnabled(false); 01058 patternCombo->setEnabled(false); 01059 patternCurrentCombo->setEnabled(false); 01060 setInjectionPattern(true); 01061 } 01062 else{ 01063 injectPatternButton->setEnabled(true); 01064 injectPatternNeurGrpCombo->setEnabled(true); 01065 patternCombo->setEnabled(true); 01066 patternCurrentCombo->setEnabled(true); 01067 01068 //Switch off sustain pattern - the pattern will be automatically deleted on next step. 01069 nemoWrapper->setSustainPattern(false); 01070 } 01071 } 01072 01073 01075 void NemoWidget::unloadSimulation(bool confirmWithUser){ 01076 //Double check that user wants to unload simulation 01077 if(confirmWithUser){ 01078 int response = QMessageBox::warning(this, "Unload?", "Are you sure that you want to unload the simulation?\nAny unsaved weight changes will be lost.", QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); 01079 if(response != QMessageBox::Ok) 01080 return; 01081 } 01082 01083 //Unload the simulation 01084 nemoWrapper->unloadSimulation(); 01085 Globals::setSimulation(NULL); 01086 01087 //Clear network display 01088 Globals::getNetworkDisplay()->setNeuronColorMap(new QHash<unsigned int, RGBColor*>()); 01089 01090 //Set buttons appropriately 01091 loadButton->setEnabled(true); 01092 unloadButton->setEnabled(false); 01093 synapseParametersButton->setEnabled(true); 01094 nemoParametersButton->setEnabled(true); 01095 controlsWidget->setEnabled(false); 01096 archiveDescriptionEdit->setText("Undescribed"); 01097 archiveCheckBox->setChecked(false);//Single archive associated with each simulation run 01098 timeStepLabel->setText("0"); 01099 01100 //Inject patterns, current etc. 01101 sustainPatternChkBox->setChecked(false); 01102 injectPatternButton->setEnabled(true); 01103 injectPatternNeurGrpCombo->setEnabled(true); 01104 patternCombo->setEnabled(true); 01105 patternCurrentCombo->setEnabled(true); 01106 01107 sustainNoiseChkBox->setChecked(false); 01108 injectNoiseButton->setEnabled(true); 01109 injectNoisePercentCombo->setEnabled(true); 01110 injectNoiseCurrentCombo->setEnabled(true); 01111 injectNoiseNeuronGroupCombo->setEnabled(true); 01112 01113 //Clean up any raster plots 01114 for(QHash<unsigned, SpikeRasterDialog*>::iterator iter = rasterDialogMap.begin(); iter != rasterDialogMap.end(); ++iter){ 01115 delete iter.value(); 01116 } 01117 rasterDialogMap.clear(); 01118 01119 //Clean up any membrane potential plots 01120 for(QHash<unsigned, MembranePotentialGraphDialog*>::iterator iter = memPotGraphDialogMap.begin(); iter != memPotGraphDialogMap.end(); ++iter){ 01121 delete iter.value(); 01122 } 01123 memPotGraphDialogMap.clear(); 01124 } 01125 01126 01128 void NemoWidget::updateProgress(int stepsCompleted, int totalSteps){ 01129 //Set flag to avoid multiple calls to progress dialog while it is redrawing 01130 if(updatingProgress) 01131 return; 01132 updatingProgress = true; 01133 01134 if(progressDialog == NULL) 01135 return; 01136 01137 //Check numbers are sensible 01138 if(stepsCompleted > totalSteps){ 01139 qCritical()<<"Progress update error: Number of steps completed is greater than the number of possible steps."; 01140 return; 01141 } 01142 01143 //Update progress 01144 if(stepsCompleted < totalSteps){ 01145 progressDialog->setValue(stepsCompleted); 01146 progressDialog->setMaximum(totalSteps); 01147 } 01148 01149 //Clear updating progress flag 01150 updatingProgress = false; 01151 } 01152 01153 01154 /*----------------------------------------------------------*/ 01155 /*------ PRIVATE METHODS ------*/ 01156 /*----------------------------------------------------------*/ 01157 01159 bool NemoWidget::checkForErrors(){ 01160 if(nemoWrapper->isError()){ 01161 qCritical()<<"NemoWrapper error: '"<<nemoWrapper->getErrorMessage()<<"'."; 01162 return true; 01163 } 01164 return false; 01165 } 01166 01167 01169 void NemoWidget::checkWidgetEnabled(){ 01170 if(Globals::networkLoaded()) 01171 mainGroupBox->setEnabled(true); 01172 else 01173 mainGroupBox->setEnabled(false); 01174 } 01175 01176 01178 void NemoWidget::createMembranePotentialColors(){ 01179 heatColorMap[-1] = new RGBColor(0.0f, 0.0f, 0.0f); 01180 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[-1]); 01181 heatColorMap[0] = new RGBColor(HEAT_COLOR_0); 01182 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[0]); 01183 heatColorMap[1] = new RGBColor(HEAT_COLOR_1); 01184 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[1]); 01185 heatColorMap[2] = new RGBColor(HEAT_COLOR_2); 01186 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[2]); 01187 heatColorMap[3] = new RGBColor(HEAT_COLOR_3); 01188 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[3]); 01189 heatColorMap[4] = new RGBColor(HEAT_COLOR_4); 01190 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[4]); 01191 heatColorMap[5] = new RGBColor(HEAT_COLOR_5); 01192 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[5]); 01193 heatColorMap[6] = new RGBColor(HEAT_COLOR_6); 01194 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[6]); 01195 heatColorMap[7] = new RGBColor(HEAT_COLOR_7); 01196 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[7]); 01197 heatColorMap[8] = new RGBColor(HEAT_COLOR_8); 01198 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[8]); 01199 heatColorMap[9] = new RGBColor(HEAT_COLOR_9); 01200 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[9]); 01201 heatColorMap[10] = new RGBColor(HEAT_COLOR_10); 01202 Globals::getNetworkDisplay()->addDefaultColor(heatColorMap[10]); 01203 } 01204 01205 01207 void NemoWidget::fillPatternCurrentCombo(){ 01208 patternCurrentCombo->addItem("Fire"); 01209 for(int i=0; i<=100; i+=10) 01210 patternCurrentCombo->addItem(QString::number(i)); 01211 } 01212 01214 QString NemoWidget::getFilePath(QString fileFilter){ 01215 QFileDialog dialog(this); 01216 dialog.setDirectory(Globals::getWorkingDirectory()); 01217 dialog.setFileMode(QFileDialog::ExistingFile); 01218 dialog.setNameFilter( QString("Configuration files (" + fileFilter + ")") ); 01219 dialog.setViewMode(QFileDialog::Detail); 01220 QStringList fileNames; 01221 if (dialog.exec()) 01222 fileNames = dialog.selectedFiles(); 01223 if(fileNames.size() > 0) 01224 return fileNames[0]; 01225 else 01226 return QString(""); 01227 } 01228 01229 01231 unsigned NemoWidget::getNeuronGroupID(QString neurGrpStr){ 01232 QRegExp regExp("[()]"); 01233 return Util::getUInt(neurGrpStr.section(regExp, 1, 1)); 01234 } 01235 01236 01241 QString NemoWidget::getPatternKey(const QString& patternComboText){ 01242 if(patternComboText == LOAD_PATTERN_STRING){ 01243 throw SpikeStreamException("Cannot inject pattern: no patterns added."); 01244 } 01245 01246 //Find the key to the pattern in the pattern map 01247 QString patternKey = ""; 01248 for(QHash<QString, Pattern>::iterator iter = patternMap.begin(); iter != patternMap.end(); ++iter){ 01249 if(iter.value().getName() == patternComboText){ 01250 patternKey = iter.key(); 01251 break; 01252 } 01253 } 01254 01255 //Check that key has been found 01256 if(patternKey.isEmpty()){ 01257 throw SpikeStreamException("Pattern not found: " + patternComboText); 01258 } 01259 01260 return patternKey; 01261 } 01262 01263 01265 QToolBar* NemoWidget::getToolBar(){ 01266 QToolBar* tmpToolBar = new QToolBar(this); 01267 01268 playAction = new QAction(QIcon(Globals::getSpikeStreamRoot() + "/images/play.png"), "Start simulation", this); 01269 connect(playAction, SIGNAL(triggered()), this, SLOT(startSimulation())); 01270 tmpToolBar->addAction (playAction); 01271 01272 stopAction = new QAction(QIcon(Globals::getSpikeStreamRoot() + "/images/stop.png"), "Stop simulation", this); 01273 connect(stopAction, SIGNAL(triggered()), this, SLOT(stopSimulation())); 01274 stopAction->setEnabled(false); 01275 tmpToolBar->addAction (stopAction); 01276 01277 stepAction = new QAction(QIcon(Globals::getSpikeStreamRoot() + "/images/step.png"), "Step simulation", this); 01278 connect(stepAction, SIGNAL(triggered()), this, SLOT(stepSimulation())); 01279 tmpToolBar->addAction (stepAction); 01280 01281 simulationRateCombo = new QComboBox(); 01282 simulationRateCombo->addItem("1"); 01283 simulationRateCombo->addItem("5"); 01284 simulationRateCombo->addItem("10"); 01285 simulationRateCombo->addItem("15"); 01286 simulationRateCombo->addItem("20"); 01287 simulationRateCombo->addItem("25"); 01288 simulationRateCombo->addItem("Max"); 01289 connect(simulationRateCombo, SIGNAL(activated(int)), this, SLOT(simulationRateChanged(int))); 01290 tmpToolBar->addWidget(simulationRateCombo); 01291 01292 timeStepLabel = new QLabel ("0"); 01293 timeStepLabel->setStyleSheet( "QLabel { margin-left: 5px; background-color: #ffffff; border-color: #555555; border-width: 2px; border-style: outset; font-weight: bold;}"); 01294 timeStepLabel->setMinimumSize(200, 20); 01295 timeStepLabel->setMaximumSize(200, 20); 01296 timeStepLabel->setAlignment(Qt::AlignCenter); 01297 tmpToolBar->addWidget(timeStepLabel); 01298 01299 QCheckBox* monitorChkBox = new QCheckBox("Monitor"); 01300 monitorChkBox->setChecked(true); 01301 connect(monitorChkBox, SIGNAL(stateChanged(int)), this, SLOT(monitorChanged(int))); 01302 tmpToolBar->addSeparator(); 01303 tmpToolBar->addWidget(monitorChkBox); 01304 01305 return tmpToolBar; 01306 } 01307 01309 void NemoWidget::loadNeuronGroups(){ 01310 injectNoiseNeuronGroupCombo->clear(); 01311 injectPatternNeurGrpCombo->clear(); 01312 01313 QList<NeuronGroupInfo> neurGrpInfoList = Globals::getNetwork()->getNeuronGroupsInfo(); 01314 foreach(NeuronGroupInfo info, neurGrpInfoList){ 01315 injectNoiseNeuronGroupCombo->addItem(info.getName() + "(" + QString::number(info.getID()) + ")"); 01316 injectPatternNeurGrpCombo->addItem(info.getName() + "(" + QString::number(info.getID()) + ")"); 01317 } 01318 } 01319 01320 01322 void NemoWidget::setInjectNoise(bool sustain){ 01323 double percentage = Util::getDouble(injectNoisePercentCombo->currentText().section(" ", 0, 0)); 01324 unsigned neurGrpID = getNeuronGroupID(injectNoiseNeuronGroupCombo->currentText()); 01325 try{ 01326 if(injectNoiseCurrentCombo->currentText() == "Fire"){ 01327 nemoWrapper->setInjectNoise(neurGrpID, percentage, sustain); 01328 } 01329 else{ 01330 nemoWrapper->setInjectCurrent(neurGrpID, percentage, Util::getDouble(injectNoiseCurrentCombo->currentText()), sustain); 01331 } 01332 } 01333 catch(SpikeStreamException& ex){ 01334 qCritical()<<ex.getMessage(); 01335 } 01336 } 01337 01338 01340 void NemoWidget::setInjectionPattern(bool sustain){ 01341 //Set pattern in the nemo wrapper 01342 try{ 01343 if(patternCurrentCombo->currentIndex() == 0)//Fire neurons 01344 nemoWrapper->setFiringInjectionPattern( 01345 patternMap[getPatternKey(patternCombo->currentText())], 01346 getNeuronGroupID(injectPatternNeurGrpCombo->currentText()), 01347 sustain 01348 ); 01349 else{ 01350 float injectionCurrent = Util::getFloat(patternCurrentCombo->currentText()); 01351 nemoWrapper->setCurrentInjectionPattern( 01352 patternMap[getPatternKey(patternCombo->currentText())], 01353 injectionCurrent, 01354 getNeuronGroupID(injectPatternNeurGrpCombo->currentText()), 01355 sustain 01356 ); 01357 } 01358 } 01359 catch(SpikeStreamException& ex){ 01360 qCritical()<<ex.getMessage(); 01361 } 01362 } 01363