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

SpikeStreamMainWindow.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "SpikeStreamMainWindow.h"
00025 #include "LogWriter.h"
00026 #include "Debug.h"
00027 #include "Utilities.h"
00028 #include "Tester.h"
00029 #include "GlobalVariables.h"
00030 #include "DatabaseManager.h"
00031 #include "PatternDialog.h"
00032 #include "ProbeDialog.h"
00033 #include "ConfigLoader.h"
00034 #include "ConnectionMatrixLoader.h"
00035 
00036 //Qt includes
00037 #include <qsplitter.h>
00038 #include <qsplashscreen.h>
00039 #include <qpixmap.h>
00040 #include <qmenubar.h>
00041 #include <qmessagebox.h>
00042 #include <qapplication.h>
00043 #include <qaccel.h>
00044 #include <qfile.h>
00045 #include <qscrollview.h>
00046 #include <qvbox.h>
00047 #include <qfiledialog.h>
00048 
00049 //Other includes
00050 #include <mysql++.h>
00051 #include <string>
00052 using namespace std;
00053 using namespace mysqlpp;
00054 
00055 
00056 //Declare static variables here for linking
00057 QString SpikeStreamMainWindow::workingDirectory = "";
00058 SpikeStreamMainWindow* SpikeStreamMainWindow::spikeStrMainWin;
00059 SpikeStreamApplication* SpikeStreamMainWindow::spikeStreamApplication;
00060 
00061 
00062 /*! Constructor. */
00063 SpikeStreamMainWindow::SpikeStreamMainWindow(SpikeStreamApplication *ssApp) : QMainWindow( 0, "SpikeStream", WDestructiveClose ){
00064         //Store a static reference to itself so that it can be accessed from anywhere
00065         spikeStrMainWin = this;
00066 
00067         //Store reference to spike stream application
00068         spikeStreamApplication = ssApp;
00069 
00070         //Get the working directory, which should be defined by the SPIKESTREAM_ROOT variable
00071         workingDirectory = getenv("SPIKESTREAM_ROOT");
00072 
00073         //Working directory is essential, so exit if it is not defined.
00074         if( workingDirectory == ""){
00075                 cerr<<"CANNOT FIND SPIKESTREAM_ROOT VARIABLE. THIS MUST BE DEFINED FOR APPLICATION TO WORK, EXITING"<<endl;
00076                 QMessageBox::critical( 0, "SpikeStream", "SPIKESTREAM_ROOT variable is not defined.\nApplication will now exit.");
00077                 delete this;
00078                 exit(1);
00079         }
00080         else if( !QFile::exists(workingDirectory) ){
00081                 cerr<<"SPIKESTREAM_ROOT VARIABLE POINTS TO AN INVALID DIRECTORY: "<<workingDirectory<<endl;
00082                 QMessageBox::critical( 0, "SpikeStream", "SPIKESTREAM_ROOT variable does not point to a valid directory.\nApplication will now exit.");
00083                 delete this;
00084                 exit(1);
00085         }
00086         else {
00087                 #ifdef PATH_DEBUG
00088                         cout<<"Working directory: "<<workingDirectory<<endl;
00089                 #endif//PATH_DEBUG
00090         }
00091 
00092         //Set up splash screen to give feedback whilst application is loading
00093         QSplashScreen *splashScreen = 0;
00094         QPixmap splashPixmap(workingDirectory + "/images/spikestream_splash.png" );
00095         splashScreen = new QSplashScreen( splashPixmap );
00096         splashScreen->show();
00097 
00098 
00099         //Set up config
00100         ConfigLoader* configLoader;
00101         if(QFile::exists(workingDirectory +  "/spikestream.config")){
00102                 configLoader = new ConfigLoader(workingDirectory + "/spikestream.config");
00103         }
00104         else{
00105                 cerr<<"Cannot find configuration file at "<<workingDirectory<<"/spikestream.config"<<endl;
00106                 QMessageBox::critical( 0, "Config Error", "Cannot find configuration file\nApplication will now exit.");
00107                 exit(1);        
00108         }
00109         
00110 
00111         //Set up the logging
00112         //Load the log level from the configuration file: 0 disables logging, 1 enables medium logging, 2 enables full logging
00113         int logLev = 0;
00114         try{
00115                 logLev = Utilities::getInt(configLoader->getStringData("log_level"));
00116         }
00117         catch(std::exception& er){// Catch-all for std exceptions
00118                 cerr<<"SpikeStreamMainWindow: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00119                 QString errorString = "Exception thrown getting log level: \"";
00120                 errorString += er.what();
00121                 errorString += "\"";
00122                 QMessageBox::critical( 0, "Config Error", errorString);
00123         }
00124 
00125         if(logLev == 0)
00126                 LogWriter::disableLogging();
00127         else{//Logging is enabled
00128                 //Set the log level
00129                 if(logLev == 1 || logLev == 2)
00130                         LogWriter::setLogLevel(logLev);
00131                 else{
00132                         cerr<<"SpikeStreamMainWindow: LOG LEVEL SHOULD BE 0, 1 OR 2"<<endl;
00133                         LogWriter::setLogLevel(1);
00134                 }
00135                 
00136                 //Find the log file
00137                 if(QFile::exists(workingDirectory + "/SpikeStream.log")){
00138                         QString logPath = workingDirectory + "/SpikeStream.log";
00139                         LogWriter::setLogPath(logPath.ascii());
00140                 }
00141                 else{
00142                         cerr<<"Cannot find log file. Creating new file."<<endl;
00143                         LogWriter::setLogPath(workingDirectory + "/SpikeStream.log");
00144                 }
00145                 
00146                 //Check to see if it has reached its maximum size defined in config file. 
00147                 //Disable logging if it is too big
00148                 unsigned int maxLogSize = 100000;
00149                 try{
00150                         maxLogSize = Utilities::getUInt(configLoader->getStringData("Max_log_size"));
00151                 }
00152                 catch(std::exception& er){// Catch-all for std exceptions
00153                         cerr<<"SpikeStreamMainWindow: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00154                         QString errorString = "Exception thrown geting max log size: \"";
00155                         errorString += er.what();
00156                         errorString += "\"";
00157                         QMessageBox::critical( 0, "Config Error", errorString);
00158                 }
00159 
00160                 QFile logFile(workingDirectory + "/SpikeStream.log");
00161                 if(logFile.size() > maxLogSize){
00162                         cerr<<"Log file is full. Logging disabled. [ Max_log_size: "<<maxLogSize<<"; Current log size: "<<logFile.size()<<" ]"<<endl;
00163                         LogWriter::disableLogging();    
00164                 }
00165                 
00166                 //Write the date and time to the log.
00167                 LogWriter::writeDate();
00168         }
00169         
00170         //Set up the Network database interface and connect to it
00171         //This will be used by many other classes, so keep reference to it
00172         networkDBInterface = new DBInterface(
00173                 configLoader->getCharData("neuralNetworkHost"), 
00174                 configLoader->getCharData("neuralNetworkUser"), 
00175                 configLoader->getCharData("neuralNetworkPassword"), 
00176                 configLoader->getCharData("neuralNetworkDatabase")
00177         );
00178         if(!networkDBInterface->connectToDatabase(true)){//Exceptions enabled
00179                 QMessageBox::critical (this, "Initialisation failure", "Connection to NeuralNetwork database failed");
00180                 exit(1);
00181         }
00182 
00183         //Set up the archive database interface and connect to it
00184         archiveDBInterface = new DBInterface(
00185                 configLoader->getCharData("archiveHost"), 
00186                 configLoader->getCharData("archiveUser"), 
00187                 configLoader->getCharData("archivePassword"), 
00188                 configLoader->getCharData("archiveDatabase")
00189         );
00190         if(!archiveDBInterface->connectToDatabase(true)){//Exceptions enabled
00191                 QMessageBox::critical (this, "Initialisation failure", "Connection to NeuralArchive database failed");
00192                 exit(1);
00193         }
00194 
00195         //Set up the pattern database interface and connect to it
00196         patternDBInterface = new DBInterface(
00197                 configLoader->getCharData("patternHost"), 
00198                 configLoader->getCharData("patternUser"), 
00199                 configLoader->getCharData("patternPassword"), 
00200                 configLoader->getCharData("patternDatabase")
00201         );
00202         if(!patternDBInterface->connectToDatabase(true)){//Exceptions enabled
00203                 QMessageBox::critical (this, "Initialisation failure", "Connection to Patterns database failed");
00204                 exit(1);
00205         }
00206 
00207         //Set up the device database interface and connect to it
00208         deviceDBInterface = new DBInterface(
00209                 configLoader->getCharData("deviceHost"), 
00210                 configLoader->getCharData("deviceUser"), 
00211                 configLoader->getCharData("devicePassword"), 
00212                 configLoader->getCharData("deviceDatabase")
00213         );
00214         if(!deviceDBInterface->connectToDatabase(true)){//Exceptions enabled
00215                 QMessageBox::critical (this, "Initialisation failure", "Connection to Devices database failed");
00216                 exit(1);
00217         }
00218 
00219         //Get the default location for saving and loading databases
00220         defaultFileLocation = configLoader->getCharData("default_file_location");
00221 
00222         //Set up tester to run any code that needs testing
00223         //Tester *tester = new Tester();
00224         //delete tester;
00225 
00226         //Set up menus. 
00227         //Add file menu.
00228         QPopupMenu * fileMenu = new QPopupMenu(this);
00229         menuBar()->insertItem("File", fileMenu);
00230         fileMenu->insertItem("Clear databases", this, SLOT(clearDatabases()), CTRL+Key_R);
00231         fileMenu->insertItem("Load databases", this, SLOT(loadDatabases()), CTRL+Key_L);
00232         fileMenu->insertItem("Save databases", this, SLOT(saveDatabases()), CTRL+Key_S);
00233         fileMenu->insertSeparator();
00234         fileMenu->insertItem("Import connection matrix", this, SLOT(importConnectionMatrix()), CTRL+Key_I);
00235         fileMenu->insertSeparator();
00236         fileMenu->insertItem("Quit", qApp, SLOT(closeAllWindows()), CTRL+Key_Q);
00237 
00238         //Add refresh menu for when changes have been made in the database independently of the application
00239         QPopupMenu *viewMenu = new QPopupMenu(this);
00240         menuBar()->insertItem("View", viewMenu);
00241         viewMenu->insertItem("Reload devices", this, SLOT(reloadDevices()), CTRL+Key_D);
00242         viewMenu->insertItem("Reload patterns", this, SLOT(reloadPatterns()), CTRL+Key_P);
00243         viewMenu->insertItem("Reload everything", this, SLOT(reloadEverything()), SHIFT+Key_F5);
00244 
00245         //Add tools menu for pattern manager and probe
00246         QPopupMenu *toolsMenu = new QPopupMenu(this);
00247         menuBar()->insertItem("Tools", toolsMenu);
00248         toolsMenu->insertItem("Pattern manager", this, SLOT(managePatterns()), Key_F6);
00249         toolsMenu->insertItem("Probe manager", this, SLOT(manageProbes()), Key_F7);
00250 
00251         //Add help menu
00252         QPopupMenu *helpMenu = new QPopupMenu(this);
00253         menuBar()->insertItem("Help", helpMenu);
00254         helpMenu->insertItem("About", this , SLOT(about()), Key_F12);
00255         
00256         
00257         //Set up panes
00258         //Set up main splitter, which will divide graphical view from editor/viewer/simulator windows
00259         QSplitter *mainSplitterWidget = new QSplitter(this);
00260         tabWidget = new QTabWidget(mainSplitterWidget);
00261         
00262         //Set up editor window and add to tab widget
00263         QSplitter *layerSplitterWidget = new QSplitter( tabWidget);
00264         layerWidget = new LayerWidget(layerSplitterWidget, networkDBInterface, deviceDBInterface);
00265         connectionWidget = new ConnectionWidget(layerSplitterWidget, networkDBInterface, deviceDBInterface);
00266         layerSplitterWidget->setOrientation(Qt::Vertical);
00267         tabWidget->addTab(layerSplitterWidget, "Editor");
00268         
00269 
00270         //Create network viewer for right half of screen
00271         unsigned int maxAutoLoadConnGrpSize = 1000000;
00272         try{
00273                 maxAutoLoadConnGrpSize = Utilities::getUInt(configLoader->getStringData("max_autoload_conngrp_size"));
00274         }
00275         catch(std::exception& er){// Catch-all for std exceptions
00276                 cerr<<"SpikeStreamMainWindow: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00277                 QString errorString = "Exception thrown getting maxAutoLoadConnGrpSize: \"";
00278                 errorString += er.what();
00279                 errorString += "\"";
00280                 QMessageBox::critical( 0, "Config Error", errorString);
00281         }
00282 
00283         networkViewer = new NetworkViewer(mainSplitterWidget, splashScreen, networkDBInterface, maxAutoLoadConnGrpSize);
00284         networkViewer->setMinimumSize(200, 60);
00285         networkViewer->setBaseSize(700, 60);
00286 
00287 
00288         //Set up viewer tab
00289         QScrollView* nwViewerPropScrollView = new QScrollView(this);
00290         QVBox* nwViewerPropViewBox = new QVBox(nwViewerPropScrollView->viewport());
00291         nwViewerPropViewBox->setMinimumSize(1000,800);
00292         nwViewerPropScrollView->addChild(nwViewerPropViewBox);
00293         networkViewerProperties = new NetworkViewerProperties(nwViewerPropViewBox, networkViewer, networkDBInterface);
00294         networkViewerProperties->setMinimumSize(800, 600);
00295         tabWidget->addTab(nwViewerPropScrollView, "Viewer");
00296 
00297 
00298         //Set up simulator tab
00299         QScrollView* simulationScrollView = new QScrollView(this);
00300         QVBox* simulationViewBox = new QVBox(simulationScrollView->viewport());
00301         simulationViewBox->setMinimumSize(1000,800);
00302         simulationScrollView->addChild(simulationViewBox);
00303         QSplitter *simulationSplitterWidget = new QSplitter(simulationViewBox);
00304         simulationSplitterWidget->setOrientation(Qt::Vertical);
00305         simulationWidget = new SimulationWidget(simulationSplitterWidget, networkDBInterface, archiveDBInterface, patternDBInterface, deviceDBInterface);
00306         simulationManager = simulationWidget->getSimulationManager();
00307 
00308         //Set up the simulation manager with the maximum load time
00309         int maxLoadTime_sec = 200;
00310         try{
00311                 maxLoadTime_sec = Utilities::getInt(configLoader->getStringData("max_neuron_data_load_time"));
00312         }
00313         catch(std::exception& er){// Catch-all for std exceptions
00314                 cerr<<"SpikeStreamMainWindow: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00315                 QString errorString = "Exception thrown getting max neuron data load time: \"";
00316                 errorString += er.what();
00317                 errorString += "\"";
00318                 QMessageBox::critical( 0, "Config Error", errorString);
00319         }
00320         simulationManager->setMaxNeurDataLoadTime_sec(maxLoadTime_sec);
00321 
00322         //Set up monitor area at bottom of simulation tab
00323         MonitorArea *simulationMonitorArea = new MonitorArea(networkDBInterface, simulationManager, simulationSplitterWidget);
00324         simulationMonitorArea->setMinimumSize(60, 200);
00325         simulationWidget->setMonitorArea(simulationMonitorArea);
00326         tabWidget->addTab(simulationScrollView, "Simulation");
00327 
00328 
00329         //Set up archive tab
00330         QScrollView* archiveScrollView = new QScrollView(this);
00331         QVBox* archiveViewBox = new QVBox(archiveScrollView->viewport());
00332         archiveViewBox->setMinimumSize(1000, 800);
00333         archiveScrollView->addChild(archiveViewBox);
00334         QSplitter *archiveSplitterWidget = new QSplitter(archiveViewBox);
00335         archiveSplitterWidget->setOrientation(Qt::Vertical);
00336         archiveWidget = new ArchiveWidget(archiveSplitterWidget, archiveDBInterface);
00337         archiveManager = archiveWidget->getArchiveManager();
00338 
00339         MonitorArea *archiveMonitorArea = new MonitorArea(archiveManager, archiveSplitterWidget);
00340         archiveMonitorArea->setMinimumSize(60, 200);
00341         archiveWidget->setMonitorArea(archiveMonitorArea);
00342         tabWidget->addTab(archiveScrollView, "Archive");
00343         
00344 
00345         //Set up layer widget connections
00346         layerWidget->setConnectionWidget(connectionWidget);
00347         
00348         //Set up network viewer references
00349         networkViewer->setNetworkViewerProperties((QWidget*)networkViewerProperties);
00350 
00351         //Set up an accelerator to switch between the tabs
00352         keyboardAccelerator = new QAccel( this );
00353         
00354         //Add all  the key combinations that will be required.
00355         keyboardAccelerator->insertItem(Key_F1);
00356         keyboardAccelerator->insertItem(Key_F2);
00357         keyboardAccelerator->insertItem(Key_F3);
00358         keyboardAccelerator->insertItem(Key_F4);
00359 
00360          //Connect up accelerator with the method that will process the key events
00361          connect (keyboardAccelerator, SIGNAL(activated(int)), this, SLOT(acceleratorKeyPressed(int)));
00362 
00363         //Finish off
00364         QPixmap iconPixmap(workingDirectory + "/images/spikestream_icon_64.png" );
00365         setIcon(iconPixmap);
00366     setCentralWidget( mainSplitterWidget );
00367         setWindowState(Qt::WindowMaximized);
00368         
00369         //Get rid of splash screen if it is showing
00370         if(splashScreen){
00371                 splashScreen->finish( this );
00372                 delete splashScreen;
00373         }
00374         
00375         //Delete config loader
00376         delete configLoader;
00377 }
00378 
00379 
00380 /*! Destructor. */
00381 SpikeStreamMainWindow::~SpikeStreamMainWindow(){
00382         #ifdef MEMORY_DEBUG
00383                 cout<<"DELETING SPIKE STREAM MAIN WINDOW"<<endl;
00384         #endif//MEMORY_DEBUG
00385         
00386         //First need to stop the simulation if it is running
00387         if(simulationManager->isInitialised()){
00388                 simulationManager->destroySimulation();
00389                 cout<<"Waiting for simulation to finish"<<endl;
00390                 bool threadFinished = simulationManager->wait(10000);
00391                 if(!threadFinished)
00392                         cerr<<"Simulation manager cannot be shut down cleanly within 10 seconds. Killing thread"<<endl;
00393         }
00394         
00395         //Need to stop archive manager if it is running
00396         if(archiveManager->isRunning()){
00397                 archiveManager->stopArchive();
00398                 cout<<"Waiting for archive manager to finish"<<endl;
00399                 bool threadFinished = archiveManager->wait(10000);
00400                 if(!threadFinished)
00401                         cerr<<"Archive manager cannot be shut down cleanly within 10 seconds. Killing thread"<<endl;
00402         }
00403 
00404         //Delete all the database handling classes
00405         delete networkDBInterface;
00406         delete archiveDBInterface;
00407         delete patternDBInterface;
00408         delete deviceDBInterface;
00409 }
00410 
00411 
00412 //--------------------------------------------------------------------------
00413 //------------------------------ PUBLIC METHODS ----------------------------
00414 //--------------------------------------------------------------------------
00415 
00416 /*! Returns a reference to the network viewer. */
00417 NetworkViewer* SpikeStreamMainWindow::getNetworkViewer(){
00418         return networkViewer;
00419 }
00420 
00421 
00422 /*! Reloads just the details about the connections assuming that the connection
00423         groups have remained the same. */
00424 void SpikeStreamMainWindow::reloadConnectionDetails(){
00425         networkViewerProperties->reloadConnectionDetails();
00426 }
00427 
00428 
00429 
00430 /*! Reloads connections after a class has made changes to the database. */
00431 void SpikeStreamMainWindow::reloadConnections(){
00432         networkViewerProperties->reloadConnections();
00433         simulationWidget->reloadConnectionGroups();
00434 }
00435 
00436 
00437 /*! Reloads neurons after a change has been made to the database. */
00438 void SpikeStreamMainWindow::reloadNeuronGroups(){
00439         networkViewerProperties->reloadNeuronGroups();
00440         simulationWidget->reloadNeuronGroups();
00441         connectionWidget->reloadConnections();
00442 }
00443 
00444 
00445 /*! When viewing individual neurons this method sets the from
00446         neuron number in the Simulation Widget, which can be used to
00447         fire a neuron or select a neuron for monitoring during a 
00448         simulation. */
00449 void SpikeStreamMainWindow::setFromNeuronID(unsigned int neurGrpID, unsigned int fromNeurNum){
00450         simulationWidget->setFromNeuronID(neurGrpID, fromNeurNum);
00451 }
00452 
00453 
00454 /*! When viewing individual neurons this method sets the to
00455         neuron number in the Simulation Widget, which can be used to
00456         select a synapse for monitoring during a simulation. */
00457 void SpikeStreamMainWindow::setToNeuronID(unsigned int toNeurNum){
00458         simulationWidget->setToNeuronID(toNeurNum);
00459 }
00460 
00461 
00462 /*! When simulation is destroyed this passes this information
00463         on to other widgets. */
00464 void SpikeStreamMainWindow::simulationDestroyed(){
00465         connectionWidget->simulationDestroyed();
00466         layerWidget->simulationDestroyed();
00467 }
00468 
00469 
00470 /*! When simulation is initialised this passes this information
00471         on to other widgets. */
00472 void SpikeStreamMainWindow::simulationInitialised(){
00473         connectionWidget->simulationInitialised();
00474         layerWidget->simulationInitialised();
00475 }
00476 
00477 
00478 //-------------------------------------------------------------------------
00479 //----------------------------------- SLOTS -------------------------------
00480 //-------------------------------------------------------------------------
00481 
00482 /*! Displays brief information about the application. */
00483 void SpikeStreamMainWindow::about(){
00484     QMessageBox::about( this, "About", "SpikeStream\nVersion 0.1 alpha\nCreated by David Gamez: david@davidgamez.eu");
00485 }
00486 
00487 void SpikeStreamMainWindow::acceleratorKeyPressed(int acceleratorID){
00488         //Get the key sequence
00489         int keySequence = keyboardAccelerator->key(acceleratorID);
00490         
00491         //Change to a different tab
00492         switch(keySequence){
00493                 case (Key_F1)://Edit tab
00494                         simulationWidget->hideOpenWindows();
00495                         archiveWidget->hideOpenWindows();
00496                         tabWidget->setCurrentPage(0);
00497                 break;
00498                 case (Key_F2)://Network viewer properties tab
00499                         simulationWidget->hideOpenWindows();
00500                         archiveWidget->hideOpenWindows();
00501                         tabWidget->setCurrentPage(1);
00502                 break;
00503                 case (Key_F3)://Simulation tab
00504                         simulationWidget->showOpenWindows();
00505                         archiveWidget->hideOpenWindows();
00506                         tabWidget->setCurrentPage(2);
00507                 break;
00508                 case(Key_F4)://Archive tab
00509                         simulationWidget->hideOpenWindows();
00510                         archiveWidget->showOpenWindows();
00511                         tabWidget->setCurrentPage(3);
00512                 break;
00513                 default:
00514                         cerr<<"SpikeStreamMainWindow: KEY SEQUENCE NOT RECOGNIZED: "<<keySequence<<endl;
00515         }
00516 }
00517 
00518 
00519 /*! Empties all databases except the Neuron, Synapse and Probe types. Useful when
00520         an error has led to out of date information in one of the tables. However all 
00521         data will be lost if this method is called. */
00522 void SpikeStreamMainWindow::clearDatabases(){
00523         /* Check that we do not have a simulation initialised. */
00524         if(SimulationManager::isInitialised()){
00525                 QMessageBox::warning(this, "Load Databases", "Databases cannot be loaded when a simulation is initialised.\nDestroy the simulation and try again.");
00526                 return;
00527         }
00528 
00529         /* Check that playback of an archive is not currently in progress. */
00530         if(ArchiveManager::isRunning()){
00531                 QMessageBox::warning(this, "Load Databases", "Databases cannot be loaded when an archive is being played back.\nStop archive playback and try again.");
00532                 return;
00533         }
00534 
00535 
00536         //Check that user wants to overwrite current database
00537         int response = QMessageBox::warning(this, "Clear Databases", "This will overwrite all data in all databases except NeuronTypes, SynapseTypes and ProbeTypes.\nDo you want to continue?", QMessageBox::Yes, QMessageBox::No, 0);
00538         if(response != QMessageBox::Yes)
00539                 return;
00540 
00541         //Unload archive if it is loaded. Database clearing will invalidate the query.
00542         archiveWidget->unloadArchive();
00543 
00544         //Execute queries to clear all databases
00545         try{
00546 
00547                 //Clear NeuralNetwork database
00548                 Query networkQuery = networkDBInterface->getQuery();
00549 
00550                 //First do all the straightforward clearing
00551                 networkQuery.reset();
00552                 networkQuery<<"DELETE FROM Connections";
00553                 networkQuery.execute();
00554 
00555                 networkQuery.reset();
00556                 networkQuery<<"DELETE FROM ConnectionGroups";
00557                 networkQuery.execute();
00558 
00559                 networkQuery.reset();
00560                 networkQuery<<"DELETE FROM Neurons";
00561                 networkQuery.execute();
00562 
00563                 networkQuery.reset();
00564                 networkQuery<<"DELETE FROM NeuronGroups";
00565                 networkQuery.execute();
00566 
00567                 networkQuery.reset();
00568                 networkQuery<<"DELETE FROM Probes";
00569                 networkQuery.execute();
00570 
00571                 networkQuery.reset();
00572                 networkQuery<<"DELETE FROM NoiseParameters";
00573                 networkQuery.execute();
00574 
00575                 networkQuery.reset();
00576                 networkQuery<<"DELETE FROM GlobalParameters";
00577                 networkQuery.execute();
00578 
00579                 //Add single blank row to global parameters
00580                 networkQuery.reset();
00581                 networkQuery<<"INSERT INTO GlobalParameters () VALUES ()";
00582                 networkQuery.execute();
00583 
00584 
00585                 //Next clear the parameter tables. Need to find these by looking in the appropriate Types tables
00586                 networkQuery.reset();
00587                 networkQuery<<"SELECT ParameterTableName FROM NeuronTypes";
00588                 Result neurTableNameRes = networkQuery.store();
00589                 for(Result::iterator paramTableIter = neurTableNameRes.begin(); paramTableIter != neurTableNameRes.end(); ++paramTableIter){
00590                         Row tableNameRow (*paramTableIter);
00591                         networkQuery.reset();
00592                         networkQuery<<"DELETE FROM "<<(std::string)tableNameRow["ParameterTableName"];
00593                         networkQuery.execute();
00594                 }
00595 
00596                 networkQuery.reset();
00597                 networkQuery<<"SELECT ParameterTableName FROM SynapseTypes";
00598                 Result synapseTableNameRes = networkQuery.store();
00599                 for(Result::iterator paramTableIter = synapseTableNameRes.begin(); paramTableIter != synapseTableNameRes.end(); ++paramTableIter){
00600                         Row tableNameRow (*paramTableIter);
00601                         networkQuery.reset();
00602                         networkQuery<<"DELETE FROM "<<(std::string)tableNameRow["ParameterTableName"];
00603                         networkQuery.execute();
00604                 }
00605 
00606                 networkQuery.reset();
00607                 networkQuery<<"SELECT ParameterTableName FROM ProbeTypes";
00608                 Result probeTableNameRes = networkQuery.store();
00609                 for(Result::iterator paramTableIter = probeTableNameRes.begin(); paramTableIter != probeTableNameRes.end(); ++paramTableIter){
00610                         Row tableNameRow (*paramTableIter);
00611                         networkQuery.reset();
00612                         networkQuery<<"DELETE FROM "<<(std::string)tableNameRow["ParameterTableName"];
00613                         networkQuery.execute();
00614                 }
00615 
00616 
00617                 //Clear NeuralArchive database
00618                 Query archiveQuery = archiveDBInterface->getQuery();
00619 
00620                 archiveQuery.reset();
00621                 archiveQuery<<"DELETE FROM NetworkData";
00622                 archiveQuery.execute();
00623 
00624                 archiveQuery.reset();
00625                 archiveQuery<<"DELETE FROM NetworkModels";
00626                 archiveQuery.execute();
00627 
00628 
00629                 //Clear Patterns database
00630                 Query patternsQuery = patternDBInterface->getQuery();
00631 
00632                 patternsQuery.reset();
00633                 patternsQuery<<"DELETE FROM PatternData";
00634                 patternsQuery.execute();
00635 
00636                 patternsQuery.reset();
00637                 patternsQuery<<"DELETE FROM PatternDescriptions";
00638                 patternsQuery.execute();
00639 
00640 
00641                 //Clear Devices database
00642                 Query devicesQuery = deviceDBInterface->getQuery();
00643 
00644                 devicesQuery.reset();
00645                 devicesQuery<<"DELETE FROM Devices";
00646                 devicesQuery.execute();
00647 
00648                 devicesQuery.reset();
00649                 devicesQuery<<"DELETE FROM SIMNOSSpikeReceptors";
00650                 devicesQuery.execute();
00651 
00652                 devicesQuery.reset();
00653                 devicesQuery<<"DELETE FROM SIMNOSComponents";
00654                 devicesQuery.execute();
00655 
00656                 devicesQuery.reset();
00657                 devicesQuery<<"DELETE FROM SynchronizationDelay";
00658                 devicesQuery.execute();
00659 
00660                 //Refresh display
00661                 reloadEverything();
00662 
00663         }
00664         catch (const BadQuery& er) {// Handle any query errors
00665                 cerr<<"SpikeStreamMainWindow: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00666                 QString errorString = "Bad query when clearing databases: \"";
00667                 errorString += er.what();
00668                 errorString += "\"";
00669                 QMessageBox::critical( 0, "Clear Databases Error", errorString);
00670         }
00671         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00672                 cerr<<"SpikeStreamMainWindow: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00673                 QString errorString = "Exception thrown clearing databases: \"";
00674                 errorString += er.what();
00675                 errorString += "\"";
00676                 QMessageBox::critical( 0, "Clear Databases Error", errorString);
00677         }
00678 }
00679 
00680 
00681 /*! Called when window is closed. 
00682         This is needed to invoke destructor of neuronapplication
00683         Could run a check on whether the user really wants to quit.
00684         However, this is not needed at present since everthing is stored in the database. */
00685 void SpikeStreamMainWindow::closeEvent( QCloseEvent* ce ){
00686         //If simulation is initialised, check that user really wants to quit
00687         if(simulationManager->isInitialised()){
00688                 int response = QMessageBox::warning(this, "Quit SpikeStream?", "Simulation is still initialised.\nDo you want to quit?", QMessageBox::Yes, QMessageBox::No, 0);
00689                 if(response != QMessageBox::Yes){
00690                         return;
00691                 }
00692         }
00693         ce->accept();
00694 }
00695 
00696 
00697 /*! Loads a neuron group and associated connections from a file. 
00698         This should be a comma separated matrix of connection weights. */
00699 void SpikeStreamMainWindow::importConnectionMatrix(){
00700         /* Check that we do not have a simulation initialised. */
00701         if(SimulationManager::isInitialised()){
00702                 QMessageBox::warning(this, "Import Connection Matrix", "Matrix cannot be loaded when a simulation is initialised.\nDestroy the simulation and try again.");
00703                 return;
00704         }
00705 
00706         /* Check that playback of an archive is not currently in progress. */
00707         if(ArchiveManager::isRunning()){
00708                 QMessageBox::warning(this, "Import Connection Matrix", "Matrix cannot be loaded when an archive is being played back.\nStop archive playback and try again.");
00709                 return;
00710         }
00711 
00712         //Warn user about limitations
00713         int response = QMessageBox::warning(this, "Import ConnectionMatrix", "This is a preliminary method that will try create a new layer at position (0,0,0) with the default neuron and synapse types\n Make sure there is enough space for the new layer.\nDo you want to continue?", QMessageBox::Yes, QMessageBox::No, 0);
00714         if(response != QMessageBox::Yes)
00715                 return;
00716 
00717         //Get the file name
00718         QString fileName = QFileDialog::getOpenFileName(defaultFileLocation, "All files (*.*)", this, "Load matrix dialog", "Choose a file to load" );
00719         if(fileName == NULL)
00720                 return;
00721 
00722         //Unload archive if it is loaded. Database loading will invalidate the query if it changes the archive database.
00723         archiveWidget->unloadArchive();
00724 
00725         //Load from the file
00726         #ifdef LOAD_MATRIX_DEBUG
00727                 cout<<"Loading connection matrix from file: "<<fileName<<endl;
00728         #endif//LOAD_MATRIX_DEBUG
00729 
00730         ConnectionMatrixLoader* matrixLoader = new ConnectionMatrixLoader(networkDBInterface);
00731         matrixLoader->loadConnectionMatrix(fileName);
00732         
00733         //Clean up database manager
00734         delete matrixLoader;
00735 
00736         //Reload the graphics
00737         reloadEverything();
00738 }
00739 
00740 
00741 /*! Loads databases from a file selected by the user.
00742         Launches database manager, which allows user to select which database to load. */
00743 void SpikeStreamMainWindow::loadDatabases(){
00744         /* Check that we do not have a simulation initialised. */
00745         if(SimulationManager::isInitialised()){
00746                 QMessageBox::warning(this, "Load Databases", "Databases cannot be loaded when a simulation is initialised.\nDestroy the simulation and try again.");
00747                 return;
00748         }
00749 
00750         /* Check that playback of an archive is not currently in progress. */
00751         if(ArchiveManager::isRunning()){
00752                 QMessageBox::warning(this, "Load Databases", "Databases cannot be loaded when an archive is being played back.\nStop archive playback and try again.");
00753                 return;
00754         }
00755 
00756 
00757         //Check that user wants to overwrite current database
00758         int response = QMessageBox::warning(this, "Load Databases", "This will overwrite all data in the databases that are loaded including Neuron, Synapse and Probe types.\nDo you want to continue?", QMessageBox::Yes, QMessageBox::No, 0);
00759         if(response != QMessageBox::Yes)
00760                 return;
00761 
00762         //Get the file name
00763         QString fileName = QFileDialog::getOpenFileName(defaultFileLocation, "Zipped SQL (*.sql.tar.gz)", this, "load database dialog", "Choose a file to load" );
00764         if(fileName == NULL)
00765                 return;
00766 
00767         //Unload archive if it is loaded. Database loading will invalidate the query if it changes the archive database.
00768         archiveWidget->unloadArchive();
00769 
00770         //Do some sorting out on the name. The user may have typed .sql.zip at the end
00771         if(!fileName.endsWith(NEURON_APPLICATION_FILE_EXTENSION))
00772                 fileName += NEURON_APPLICATION_FILE_EXTENSION;
00773 
00774         //Load from the file
00775         #ifdef LOAD_DATABASES_DEBUG
00776                 cout<<"Loading databases from file: "<<fileName<<endl;
00777         #endif//SAVE_DATABASES_DEBUG
00778 
00779         DatabaseManager* dbManager = new DatabaseManager(this, fileName, false, networkDBInterface, archiveDBInterface, patternDBInterface, deviceDBInterface);
00780         dbManager->exec();
00781         
00782         //Clean up database manager
00783         delete dbManager;
00784 
00785         //Reload the graphics
00786         reloadEverything();
00787 }
00788 
00789 
00790 /*! Launches the pattern manager, which is used to load and delete patterns from the database. */
00791 void SpikeStreamMainWindow::managePatterns(){
00792         PatternDialog* patternDialog = new PatternDialog(this, patternDBInterface);
00793         patternDialog->exec();
00794         delete patternDialog;
00795 }
00796 
00797 
00798 /*! Launches a probe manager, which enables the user to add or remove probes. */
00799 void SpikeStreamMainWindow::manageProbes(){
00800         ProbeDialog* probeDialog = new ProbeDialog(this, networkDBInterface);
00801         probeDialog->exec();
00802         delete probeDialog;
00803 }
00804 
00805 
00806 /*! Menu item triggers this, which reloads the device table in the simulation widget. */
00807 void SpikeStreamMainWindow::reloadDevices(){
00808         simulationWidget->reloadDevices();
00809 
00810 }
00811 
00812 
00813 /*! Reloads neuron groups and connections from the database. */
00814 void SpikeStreamMainWindow::reloadEverything(){
00815         try{
00816                 layerWidget->reloadNeuronGroups();
00817                 connectionWidget->reloadConnections();
00818                 simulationWidget->reloadNeuronGroups();
00819                 simulationWidget->reloadConnectionGroups();
00820                 networkViewerProperties->reloadConnections();
00821                 networkViewerProperties->reloadNeuronGroups();
00822                 networkViewer->reloadEverything();
00823         }
00824         catch (const BadQuery& er) {// Handle any query errors
00825                 cerr<<"SpikeStreamMainWindow: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00826                 QString errorString = "Bad query reloading everything: \"";
00827                 errorString += er.what();
00828                 errorString += "\"";
00829                 QMessageBox::critical( 0, "Reload Error", errorString);
00830         }
00831         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00832                 cerr<<"SpikeStreamMainWindow: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00833                 QString errorString = "Exception thrown reloading everything: \"";
00834                 errorString += er.what();
00835                 errorString += "\"";
00836                 QMessageBox::critical( 0, "Reload Error", errorString);
00837         }
00838         catch (std::exception& er) {// Catch-all for any other MySQL++ exceptions
00839                 cerr<<"SpikeStreamMainWindow: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00840                 QString errorString = "Exception thrown reloading everything: \"";
00841                 errorString += er.what();
00842                 errorString += "\"";
00843                 QMessageBox::critical( 0, "Reload Error", errorString);
00844         }
00845 }
00846 
00847 
00848 /*! Reloads patterns after they have been added or deleted. */
00849 void SpikeStreamMainWindow::reloadPatterns(){
00850         simulationWidget->reloadPatterns();
00851 }
00852 
00853 
00854 /*! Saves databases 
00855         Allows user to choose file and then launches database manager so that user can choose
00856         which databases to save. */
00857 void SpikeStreamMainWindow::saveDatabases(){
00858     QString fileName = QFileDialog::getSaveFileName(defaultFileLocation, "Zipped SQL (*.sql.tar.gz)", this, "save file dialog", "Choose a filename to save under" );
00859         if(fileName == NULL)
00860                 return;
00861 
00862         //First do some sorting out on the name. The user may have typed .sql.gz at the end
00863         if(!fileName.endsWith(NEURON_APPLICATION_FILE_EXTENSION))
00864                 fileName += NEURON_APPLICATION_FILE_EXTENSION;
00865 
00866         //See if the file already exists and check if user wants to save if it does
00867         if(QFile::exists(fileName)){
00868                 int response = QMessageBox::question(this, "Overwrite File?", "This file already exists.\nDo you want to overwrite it?", "Yes", "No", QString::null, 1, 0);
00869                 if(response == 1)
00870                         return;
00871                 else
00872                         QFile::remove(fileName);
00873         }
00874                 
00875         //Save the file
00876         #ifdef SAVE_DATABASES_DEBUG
00877                 cout<<"Saving databases in file: "<<fileName<<endl;
00878         #endif//SAVE_DATABASES_DEBUG
00879 
00880         DatabaseManager* dbManager = new DatabaseManager(this, fileName, true, networkDBInterface, archiveDBInterface, patternDBInterface, deviceDBInterface);
00881         dbManager->exec();
00882 
00883         //Clean up dbManager
00884         delete dbManager;
00885 }
00886 
00887 

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