SpikeStream Library  0.2
NetworkDaoThread.cpp
Go to the documentation of this file.
00001 //SpikeStream includes
00002 #include "ConfigLoader.h"
00003 #include "Connection.h"
00004 #include "GlobalVariables.h"
00005 #include "NetworkDaoThread.h"
00006 #include "Neuron.h"
00007 #include "PerformanceTimer.h"
00008 #include "SpikeStreamException.h"
00009 #include "SpikeStreamDBException.h"
00010 #include "Util.h"
00011 using namespace spikestream;
00012 
00013 #include <iostream>
00014 using namespace std;
00015 
00017 #define TIME_PERFORMANCE
00018 
00020 //#define DEBUG
00021 
00022 
00024 NetworkDaoThread::NetworkDaoThread(const DBInfo& dbInfo, const QString& name) : NetworkDao(dbInfo) {
00025         this->setObjectName(name);
00026     currentTask = NO_TASK_DEFINED;
00027     clearError();
00028     stopThread = true;
00029         progressMessage = "Not running";
00030 
00031         //Load up configuration parameters
00032         ConfigLoader configLoader;
00033         numConBuffers = Util::getInt(configLoader.getParameter("number_insert_connection_buffers"));
00034         numNeurBuffers = Util::getInt(configLoader.getParameter("number_insert_neuron_buffers"));
00035 }
00036 
00037 
00039 NetworkDaoThread::~NetworkDaoThread(){
00040 }
00041 
00042 
00043 /*----------------------------------------------------------*/
00044 /*-----                 PUBLIC METHODS                 -----*/
00045 /*----------------------------------------------------------*/
00046 
00048 void NetworkDaoThread::prepareAddConnectionGroup(unsigned int networkID, ConnectionGroup* connGrp){
00049     //Copy connection group into a list and call the mai nconnection group adding method
00050     QList<ConnectionGroup*> tmpConGrpList;
00051     tmpConGrpList.append(connGrp);
00052     prepareAddConnectionGroups(networkID, tmpConGrpList);
00053 }
00054 
00055 
00057 void NetworkDaoThread::prepareAddConnectionGroups(unsigned int networkID, QList<ConnectionGroup*>& connGrpList){
00058     //Store necessary variables
00059     this->networkID = networkID;
00060     this->connectionGroupList = connGrpList;
00061 
00062     //Set the task that will run when the thread starts
00063     currentTask = ADD_CONNECTION_GROUPS_TASK;
00064 
00065     //Record the total number of steps that the task involves
00066     totalNumberOfSteps = 1;
00067 }
00068 
00069 
00071 void NetworkDaoThread::prepareAddNeuronGroup(unsigned int networkID, NeuronGroup* neurGrp){
00072     //Copy neuron group into a list and call the main method to add neuron groups
00073     QList<NeuronGroup*> tmpNeurGrpList;
00074     tmpNeurGrpList.append(neurGrp);
00075     prepareAddNeuronGroups(networkID, tmpNeurGrpList);
00076 }
00077 
00078 
00080 void NetworkDaoThread::prepareAddNeuronGroups(unsigned int networkID, QList<NeuronGroup*>& neurGrpList){
00081         //Store necessary variables
00082     this->networkID = networkID;
00083     this->neuronGroupList = neurGrpList;
00084 
00085     //Set the task that will run when the thread starts
00086     currentTask = ADD_NEURON_GROUPS_TASK;
00087 
00088     //Record the total number of steps that the task involves
00089     totalNumberOfSteps = 1;
00090 }
00091 
00092 
00094 void NetworkDaoThread::prepareDeleteConnectionGroups(unsigned int networkID, QList<unsigned int>& conGrpList){
00095         //Store necessary variables
00096         this->networkID = networkID;
00097         this->connectionGroupIDList = conGrpList;
00098 
00099         //Set the task that will run when the thread starts
00100         currentTask = DELETE_CONNECTION_GROUPS_TASK;
00101 
00102         //Record the total number of steps that the task involves
00103         totalNumberOfSteps = 1;
00104         progressMessage = "Deleting connection groups.";
00105 }
00106 
00107 
00109 void NetworkDaoThread::prepareDeleteNeuronGroups(unsigned int networkID, QList<unsigned int>& neurGrpList){
00110         //Store necessary variables
00111         this->networkID = networkID;
00112         this->neuronGroupIDList = neurGrpList;
00113 
00114         //Set the task that will run when the thread starts
00115         currentTask = DELETE_NEURON_GROUPS_TASK;
00116 
00117         //Record the total number of steps that the task involves
00118         totalNumberOfSteps = 1;
00119         progressMessage = "Deleting neuron groups.";
00120 }
00121 
00122 
00124 void NetworkDaoThread::prepareLoadConnections(const QList<ConnectionGroup*>& connGrpList){
00125     //Store necessary variables
00126     this->connectionGroupList = connGrpList;
00127 
00128     //Set the taks that will run when the thread starts
00129     currentTask = LOAD_CONNECTIONS_TASK;
00130         progressMessage = "Loading connections";
00131 }
00132 
00133 
00135 void NetworkDaoThread::prepareLoadConnections(ConnectionGroup* connGrp){
00136     //Store necessary variables
00137     connectionGroupList.clear();
00138     connectionGroupList.append(connGrp);
00139 
00140     //Set the task that will run when the thread starts
00141     currentTask = LOAD_CONNECTIONS_TASK;
00142         progressMessage = "Loading connections";
00143 }
00144 
00145 
00147 void NetworkDaoThread::prepareLoadNeurons(const QList<NeuronGroup*>& neurGrpList){
00148     //Store necessary variables
00149     this->neuronGroupList = neurGrpList;
00150 
00151     //Set the task that will run when the thread starts
00152     currentTask = LOAD_NEURONS_TASK;
00153         progressMessage = "Loading neurons";
00154 }
00155 
00156 
00158 void NetworkDaoThread::prepareLoadNeurons(NeuronGroup* neurGrp){
00159         //Store necessary variables
00160         neuronGroupList.clear();
00161         neuronGroupList.append(neurGrp);
00162 
00163         //Set the task that will run when the thread starts
00164         currentTask = LOAD_NEURONS_TASK;
00165         progressMessage = "Loading neurons";
00166 }
00167 
00168 
00170 void NetworkDaoThread::clearError(){
00171     errorMessage = "";
00172     error = false;
00173 }
00174 
00175 
00178 void NetworkDaoThread::run(){
00179     stopThread = false;
00180     clearError();
00181     numberOfCompletedSteps = 0;
00182     try{
00183         //Connect to the database now that we are in a separate thread
00184                 connectToDatabase();
00185 
00186                 switch(currentTask){
00187                         case ADD_NEURON_GROUPS_TASK:
00188                                 addNeuronGroups();
00189                         break;
00190                         case ADD_CONNECTION_GROUPS_TASK:
00191                                 addConnectionGroups();
00192                         break;
00193                         case DELETE_CONNECTION_GROUPS_TASK:
00194                                 deleteConnectionGroups();
00195                         break;
00196                         case DELETE_NETWORK_TASK:
00197                                 deleteConnectionGroups();
00198                                 deleteNeuronGroups();
00199                                 deleteNetwork();
00200                         break;
00201                         case DELETE_NEURON_GROUPS_TASK:
00202                                 deleteNeuronGroups();
00203                         break;
00204                         case LOAD_CONNECTIONS_TASK:
00205                                 loadConnections();
00206                         break;
00207                         case LOAD_NEURONS_TASK:
00208                                 loadNeurons();
00209                         break;
00210                         case SAVE_NETWORK_TASK:
00211                                 saveNetwork();
00212                         break;
00213                         case SAVE_TEMP_WEIGHTS_TASK:
00214                                 saveTempWeights();
00215                         break;
00216                         default:
00217                                 setError("NetworkDaoThread started without defined task.");
00218                 }
00219 
00220                 //Database connection can be closed
00221                 closeDatabaseConnection();
00222     }
00223     catch(SpikeStreamException& ex){
00224                 setError("NetworkDaoThread: SpikeStreamException thrown carrying out current task: " + ex.getMessage());
00225     }
00226     catch(...){
00227                 setError("Unrecognized exception thrown carrying out current task.");
00228     }
00229 
00230     //Current task is complete
00231         neuronGroupIDList.clear();
00232         neuronGroupList.clear();
00233         connectionGroupIDList.clear();
00234         connectionGroupList.clear();
00235         networkID = 0;
00236     currentTask = NO_TASK_DEFINED;
00237     stopThread = true;
00238 }
00239 
00240 
00242 void NetworkDaoThread::startDeleteNetwork(unsigned networkID){
00243         this->networkID = networkID;
00244         //Store list of connection group IDs
00245         connectionGroupIDList.clear();
00246         QList<ConnectionGroupInfo> conGrpInfoList;
00247         getConnectionGroupsInfo(networkID, conGrpInfoList);
00248         foreach(ConnectionGroupInfo conGrpInfo, conGrpInfoList)
00249                 connectionGroupIDList.append(conGrpInfo.getID());
00250 
00251         //Store list of neuron group IDs
00252         neuronGroupIDList.clear();
00253         QList<NeuronGroupInfo> neurGrpInfoList;
00254         getNeuronGroupsInfo(networkID, neurGrpInfoList);
00255         foreach(NeuronGroupInfo neurGrpInfo, neurGrpInfoList)
00256                 neuronGroupIDList.append(neurGrpInfo.getID());
00257 
00258         //Prepare and start task
00259         currentTask = DELETE_NETWORK_TASK;
00260         progressMessage = "Deleting network";
00261         start();
00262 }
00263 
00264 
00266 void NetworkDaoThread::startSaveNetwork(unsigned networkID, QList<NeuronGroup*> newNeuronGroups, QList<ConnectionGroup*> newConnectionGroups, QList<unsigned> deleteNeuronGroupIDs, QList<unsigned> deleteConnectionGroupIDs, QList<ConnectionGroup*> volatileConnectionGroups){
00267         //Store data
00268         this->networkID = networkID;
00269         this->neuronGroupList = newNeuronGroups;
00270         this->connectionGroupList = newConnectionGroups;
00271         this->neuronGroupIDList = deleteNeuronGroupIDs;
00272         this->connectionGroupIDList = deleteConnectionGroupIDs;
00273         this->volatileConnectionGroupList = volatileConnectionGroups;
00274 
00275         //Start thread running
00276         currentTask = SAVE_NETWORK_TASK;
00277         progressMessage = "Saving network";
00278         start();
00279 }
00280 
00281 
00283 void NetworkDaoThread::startSaveTempWeights(QList<ConnectionGroup*>& connectionGroupList){
00284         //Store data
00285         this->volatileConnectionGroupList = connectionGroupList;
00286 
00287         //Start thread running
00288         currentTask = SAVE_TEMP_WEIGHTS_TASK;
00289         numberOfCompletedSteps = 0;
00290         totalNumberOfSteps = 0;
00291         progressMessage = "Saving temporary weights";
00292         start();
00293 }
00294 
00295 
00297 void NetworkDaoThread::stop(){
00298     stopThread = true;
00299 }
00300 
00301 
00302 /*----------------------------------------------------------*/
00303 /*-----                PRIVATE METHODS                 -----*/
00304 /*----------------------------------------------------------*/
00305 
00309 void NetworkDaoThread::addConnectionGroups(){
00310         //Reset progress measure
00311         numberOfCompletedSteps = 0;
00312         totalNumberOfSteps = connectionGroupList.size();
00313         progressMessage = "Adding Connections";
00314 
00315     //Work through the list of connection groups
00316         for(QList<ConnectionGroup*>::iterator iter = connectionGroupList.begin(); iter != connectionGroupList.end() && !stopThread; ++iter){
00317                 //Get a pointer to the connection group
00318                 ConnectionGroup* connectionGroup = *iter;
00319 
00320                 //Get a copy of the information about the connection group
00321                 ConnectionGroupInfo connGrpInfo = connectionGroup->getInfo();
00322 
00323                 //Build query string
00324                 QString queryStr = "INSERT INTO ConnectionGroups (NetworkID, Description, FromNeuronGroupID, ToNeuronGroupID, Parameters, SynapseTypeID ) VALUES (";
00325                 queryStr += QString::number(networkID) + ", ";
00326                 queryStr += "'" + connGrpInfo.getDescription() + "', ";
00327                 queryStr += QString::number(connGrpInfo.getFromNeuronGroupID()) + ", ";
00328                 queryStr += QString::number(connGrpInfo.getToNeuronGroupID()) + ", ";
00329                 queryStr += "'" + connGrpInfo.getParameterXML() + "', ";
00330                 queryStr += QString::number(connGrpInfo.getSynapseTypeID()) + ")";
00331                 QSqlQuery query = getQuery(queryStr);
00332                 executeQuery(query);
00333 
00334                 //Check id is correct and add to connection group info if it is
00335                 int lastInsertID = query.lastInsertId().toInt();
00336                 if(lastInsertID >= START_CONNECTIONGROUP_ID)
00337                         connectionGroup->setID(lastInsertID);
00338                 else{
00339                         throw SpikeStreamException("Insert ID for ConnectionGroup is invalid.");
00340                 }
00341 
00342                 //Add entry for connection group parameters
00343                 //Get name of table
00344                 SynapseType synapseType = getSynapseType(connGrpInfo.getSynapseTypeID());
00345 
00346                 //Add parameter table entry for this connection group
00347                 executeQuery( "INSERT INTO " + synapseType.getParameterTableName() + "(ConnectionGroupID) VALUES (" + QString::number(connectionGroup->getID()) + ")" );
00348 
00349                 //Set synapse parameters to default values if they have not been set
00350                 if(!connectionGroup->parametersSet()){
00351                         QHash<QString, double> tmpParamMap = getDefaultSynapseParameters(connectionGroup->getSynapseTypeID());
00352                         connectionGroup->setParameters(tmpParamMap);
00353                 }
00354 
00355                 //Copy parameters from connection group into parameter table
00356                 QHash<QString, double> tmpParamMap = connectionGroup->getParameters();
00357                 setSynapseParameters(connectionGroup->getInfo(), tmpParamMap);
00358 
00359                 #ifdef TIME_PERFORMANCE
00360                         PerformanceTimer timer;
00361                 #endif//TIME_PERFORMANCE
00362 
00363                 //Build query
00364                 query = getQuery();
00365                 queryStr = "INSERT INTO Connections ( ConnectionGroupID, FromNeuronID, ToNeuronID, Delay, Weight) VALUES ";
00366                 for(int i=0; i<numConBuffers-1; ++i)
00367                         queryStr += "(?, ?, ?, ?, ?),";
00368                 queryStr += "(?, ?, ?, ?, ?)";
00369                 query.prepare(queryStr);
00370 
00371                 //Add connections to database
00372                 int conCntr = 0, offset = 0, conAddedCntr = 0;
00373                 QList<Connection*> tmpConList;
00374                 ConnectionIterator endConGrp = connectionGroup->end();
00375                 for(ConnectionIterator iter = connectionGroup->begin(); iter != endConGrp && !stopThread; ++iter){
00376                         offset = 5 * (conCntr % numConBuffers);
00377 
00378                         //Bind values to query
00379                         tmpConList.append(&(*iter));
00380                         query.bindValue(0 + offset, connectionGroup->getID());
00381                         query.bindValue(1 + offset, iter->getFromNeuronID());
00382                         query.bindValue(2 + offset, iter->getToNeuronID());
00383                         query.bindValue(3 + offset, iter->getDelay());
00384                         query.bindValue(4 + offset, iter->getWeight());
00385 
00386                         //Execute query
00387                         if(conCntr % numConBuffers == numConBuffers-1){
00388                                 executeQuery(query);
00389 
00390                                 //Add connection id to connection - last insert id is the id of the first connection in the list of value entries
00391                                 int lastInsertID = query.lastInsertId().toInt();
00392                                 if( (lastInsertID + tmpConList.size()) > LAST_CONNECTION_ID )
00393                                         throw SpikeStreamException("Database generated connection ID is out of range: " + QString::number(lastInsertID + tmpConList.size()) + ". It must be less than or equal to " + QString::number(LAST_CONNECTION_ID));
00394                                 if(lastInsertID < START_CONNECTION_ID)
00395                                         throw SpikeStreamException("Insert ID for Connection is invalid.");
00396                                 if(tmpConList.size() != numConBuffers)
00397                                         throw SpikeStreamException("Temporary connection list size " + QString::number(tmpConList.size()) + " does not match number of buffers: " + QString::number(numConBuffers));
00398 
00399                                 //Set connection ID in connection groups
00400                                 for(int i=0; i<tmpConList.size(); ++i){
00401                                         tmpConList.at(i)->setID(lastInsertID + i);
00402                                 }
00403 
00404                                 //Count number of connections that have been added
00405                                 conAddedCntr += numConBuffers;
00406 
00407                                 //Clear up list
00408                                 tmpConList.clear();
00409                         }
00410 
00411                         //Keep track of the number of connections
00412                         ++conCntr;
00413                 }
00414 
00415                 //Add remaining connections individually
00416                 if(!tmpConList.isEmpty() && !stopThread){
00417                         query = getQuery();
00418                         query.prepare("INSERT INTO Connections ( ConnectionGroupID, FromNeuronID, ToNeuronID, Delay, Weight) VALUES (?, ?, ?, ?, ?)");
00419                         for(QList<Connection*>::iterator iter = tmpConList.begin(); iter != tmpConList.end(); ++iter){
00420                                 query.bindValue(0, connectionGroup->getID());
00421                                 query.bindValue(1, (*iter)->getFromNeuronID());
00422                                 query.bindValue(2, (*iter)->getToNeuronID());
00423                                 query.bindValue(3, (*iter)->getDelay());
00424                                 query.bindValue(4, (*iter)->getWeight());
00425 
00426                                 //Execute query
00427                                 executeQuery(query);
00428 
00429                                 //Add connection id to connection
00430                                 int lastInsertID = query.lastInsertId().toInt();
00431                                 if( lastInsertID > LAST_CONNECTION_ID )
00432                                         throw SpikeStreamException("Database generated connection ID is out of range: " + QString::number(lastInsertID) + ". It must be less than or equal to " + QString::number(LAST_CONNECTION_ID));
00433                                 if(lastInsertID < START_CONNECTION_ID)
00434                                         throw SpikeStreamException("Insert ID for Connection is invalid.");
00435                                 (*iter)->setID(lastInsertID);
00436 
00437                                 //Count number of connections that have been added
00438                                 ++conAddedCntr;
00439                         }
00440                 }
00441 
00442                 //Check that we have added all the connections
00443                 if(!stopThread && (connectionGroup->size() != conAddedCntr) )
00444                         throw SpikeStreamException("Number of connections added to database: " + QString::number(conAddedCntr) + " does not match size of connection group: " + QString::number(connectionGroup->size()));
00445 
00446                 //Update progress
00447                 ++numberOfCompletedSteps;
00448 
00449                 #ifdef TIME_PERFORMANCE
00450                         timer.printTime("Number of buffers: " + QString::number(numConBuffers) + ". Number of connections remaining: " + QString::number(tmpConList.size()) + ". Adding " + QString::number(conCntr) + " connections");
00451                 #endif//TIME_PERFORMANCE
00452     }
00453 
00454         //Clean up connection groups if task was cancelled.
00455         if(stopThread){
00456                 connectionGroupIDList.clear();
00457                 foreach(ConnectionGroup* conGrp, connectionGroupList)
00458                         connectionGroupIDList.append(conGrp->getID());
00459                 deleteConnectionGroups();
00460         }
00461 }
00462 
00463 
00466 void NetworkDaoThread::addNeuronGroups(){
00467         //Reset progress measure
00468         numberOfCompletedSteps = 0;
00469         totalNumberOfSteps = neuronGroupList.size();
00470         progressMessage = "Adding Neurons";
00471 
00472     //Check that parameters have been set correctly
00473     if(networkID == 0){
00474                 setError("Network ID has not been set.");
00475                 return;
00476     }
00477     //Work through the list of neuron groups
00478         for(QList<NeuronGroup*>::iterator neurGrpIter = neuronGroupList.begin(); neurGrpIter != neuronGroupList.end() && !stopThread; ++neurGrpIter){
00479                 //User friendly pointer to group
00480                 NeuronGroup* neuronGroup = *neurGrpIter;
00481 
00482                 //Get information about the neuron group
00483                 NeuronGroupInfo neurGrpInfo = neuronGroup->getInfo();
00484 
00485                 //Add the neuron group first
00486                 QString queryStr = "INSERT INTO NeuronGroups (NetworkID, Name, Description, Parameters, NeuronTypeID ) VALUES (";
00487                 queryStr += QString::number(networkID) + ", ";
00488                 queryStr += "'" + neurGrpInfo.getName() + "', '" + neurGrpInfo.getDescription() + "', '" + neurGrpInfo.getParameterXML() + "', ";
00489                 queryStr += QString::number(neurGrpInfo.getNeuronTypeID()) + ")";
00490                 QSqlQuery query = getQuery(queryStr);
00491                 executeQuery(query);
00492 
00493                 //Check id is correct and add to neuron group info if it is
00494                 int lastInsertID = query.lastInsertId().toInt();
00495                 if(lastInsertID >= START_NEURONGROUP_ID)
00496                         neuronGroup->setID(lastInsertID);//Set this on neuron group, not on the copied info
00497                 else{
00498                         setError("Insert ID for NeuronGroup is invalid.");
00499                         return;
00500                 }
00501 
00502                 //Add entry for neuron group parameters
00503                 //Get name of table
00504                 NeuronType neurType = getNeuronType(neurGrpInfo.getNeuronTypeID());
00505 
00506                 //Add parameter table entry for this neuron group
00507                 executeQuery( "INSERT INTO " + neurType.getParameterTableName() + "(NeuronGroupID) VALUES (" + QString::number(neuronGroup->getID()) + ")" );
00508 
00509                 //Check neuron group has parameters set and add default parameters if not
00510                 if(!neuronGroup->parametersSet()){
00511                         QHash<QString, double> tmpParamMap = getDefaultNeuronParameters(neuronGroup->getNeuronTypeID());
00512                         neuronGroup->setParameters(tmpParamMap);
00513                 }
00514 
00515                 //Copy parameters from neuron group into parameter table
00516                 QHash<QString, double> tmpParamMap = neuronGroup->getParameters();
00517                 setNeuronParameters(neuronGroup->getInfo(), tmpParamMap);
00518 
00519                 #ifdef TIME_PERFORMANCE
00520                         PerformanceTimer timer;
00521                 #endif//TIME_PERFORMANCE
00522 
00523                 //Build query
00524                 query = getQuery();
00525                 queryStr = "INSERT INTO Neurons (NeuronGroupID, X, Y, Z) VALUES ";
00526                 for(int i=0; i<numNeurBuffers-1; ++i)
00527                         queryStr += "(?, ?, ?, ?),";
00528                 queryStr += "(?, ?, ?, ?)";
00529                 query.prepare(queryStr);
00530 
00531                 //Add neurons to database
00532                 int neurCntr = 0, offset = 0, neurAddedCntr = 0, tmpNeurGrpID = neuronGroup->getID();
00533                 NeuronMap* newNeurMap = new NeuronMap();
00534                 QList<Neuron*> tmpNeurList;
00535                 NeuronIterator endNeurGrp = neuronGroup->end();
00536                 for(NeuronIterator neurIter = neuronGroup->begin(); neurIter != endNeurGrp && !stopThread; ++neurIter){
00537                         offset = 4 * (neurCntr % numNeurBuffers);
00538 
00539                         //Bind values to query
00540                         tmpNeurList.append(neurIter.value());
00541                         query.bindValue(0 + offset, tmpNeurGrpID);
00542                         query.bindValue(1 + offset, neurIter.value()->getXPos());
00543                         query.bindValue(2 + offset, neurIter.value()->getYPos());
00544                         query.bindValue(3 + offset, neurIter.value()->getZPos());
00545 
00546                         //Execute query if we have added a whole number of buffers
00547                         if(neurCntr % numNeurBuffers == numNeurBuffers-1){
00548                                 executeQuery(query);
00549 
00550                                 //Add neuron id to neuron - last insert id is the id of the first neuron in the list of value entries
00551                                 int lastInsertID = query.lastInsertId().toInt();
00552                                 if( (lastInsertID + tmpNeurList.size()) > LAST_NEURON_ID )
00553                                         throw SpikeStreamException("Database generated neuron ID is out of range: " + QString::number(lastInsertID + tmpNeurList.size()) + ". It must be less than or equal to " + QString::number(LAST_NEURON_ID));
00554                                 if(lastInsertID < START_NEURON_ID)
00555                                         throw SpikeStreamException("Insert ID for Neuron is invalid.");
00556                                 if(tmpNeurList.size() != numNeurBuffers)
00557                                         throw SpikeStreamException("Temporary neuron list size " + QString::number(tmpNeurList.size()) + " does not match number of buffers: " + QString::number(numNeurBuffers));
00558 
00559                                 //Set neuron IDs and add neurons to new map with the new ID
00560                                 for(int i=0; i<tmpNeurList.size(); ++i){
00561                                         tmpNeurList.at(i)->setID(lastInsertID + i);
00562                                         (*newNeurMap)[lastInsertID + i] = tmpNeurList.at(i);
00563                                 }
00564 
00565                                 //Count number of neurons that have been added
00566                                 neurAddedCntr += numNeurBuffers;
00567 
00568                                 //Clear up list
00569                                 tmpNeurList.clear();
00570                         }
00571 
00572                         //Keep track of the number of neurons
00573                         ++neurCntr;
00574                 }
00575 
00576                 //Add remaining neurons individually
00577                 if(!tmpNeurList.isEmpty()){
00578                         query = getQuery();
00579                         query.prepare("INSERT INTO Neurons ( NeuronGroupID, X, Y, Z) VALUES (?, ?, ?, ?)");
00580                         for(QList<Neuron*>::iterator neurListIter = tmpNeurList.begin(); neurListIter != tmpNeurList.end(); ++neurListIter){
00581                                 query.bindValue(0, tmpNeurGrpID);
00582                                 query.bindValue(1, (*neurListIter)->getXPos());
00583                                 query.bindValue(2, (*neurListIter)->getYPos());
00584                                 query.bindValue(3, (*neurListIter)->getZPos());
00585 
00586                                 //Execute query
00587                                 executeQuery(query);
00588 
00589                                 //Add neuron id to neuron
00590                                 int lastInsertID = query.lastInsertId().toInt();
00591                                 if( (lastInsertID) > LAST_NEURON_ID )
00592                                         throw SpikeStreamException("Database generated neuron ID is out of range: " + QString::number(lastInsertID) + ". It must be less than or equal to " + QString::number(LAST_NEURON_ID));
00593                                 if(lastInsertID < START_NEURON_ID)
00594                                         throw SpikeStreamException("Insert ID for Neuron is invalid.");
00595                                 (*neurListIter)->setID(lastInsertID);
00596                                 (*newNeurMap)[lastInsertID] = *neurListIter;
00597 
00598                                 //Count number of neurons that have been added
00599                                 ++neurAddedCntr;
00600                         }
00601                 }
00602 
00603                 //Check that we have added all the neurons
00604                 if(!stopThread && (neuronGroup->size() != neurAddedCntr))
00605                         throw SpikeStreamException("Number of neurons added to database: " + QString::number(neurAddedCntr) + " does not match size of neuron group: " + QString::number(neuronGroup->size()));
00606 
00607                 //Set the start ID of the neuron group
00608                 NetworkDao networkDao(this->getDBInfo());
00609                 neuronGroup->setStartNeuronID( networkDao.getStartNeuronID(tmpNeurGrpID) );
00610 
00611                 #ifdef TIME_PERFORMANCE
00612                         timer.printTime("Adding neurons. Number of buffers: " + QString::number(numNeurBuffers) + ". Number of neurons remaining: " + QString::number(tmpNeurList.size()) + ". Added " + QString::number(neurAddedCntr) + " neurons");
00613                 #endif//TIME_PERFORMANCE
00614 
00615                 //Add the new map to the neuron group. This should also clean up the old map
00616                 neuronGroup->setNeuronMap(newNeurMap);
00617 
00618                 //Track progress
00619                 ++numberOfCompletedSteps;
00620     }
00621 
00622         //Clean up neuron groups if task was cancelled.
00623         if(stopThread){
00624                 neuronGroupIDList.clear();
00625                 foreach(NeuronGroup* neurGrp, neuronGroupList)
00626                         neuronGroupIDList.append(neurGrp->getID());
00627                 deleteNeuronGroups();
00628         }
00629 }
00630 
00631 
00633 void NetworkDaoThread::deleteConnectionGroups(){
00634         numberOfCompletedSteps = 0;
00635         totalNumberOfSteps = connectionGroupIDList.size();
00636         progressMessage = "Deleting connection groups";
00637 
00638         //Check that network ID is valid
00639         if(networkID == 0){
00640                 setError("Network ID has not been set.");
00641                 return;
00642         }
00643 
00644         //Work through the list of connection groups
00645         foreach(unsigned int conGroupID, connectionGroupIDList){
00646                 executeQuery("DELETE FROM Connections WHERE ConnectionGroupID=" + QString::number(conGroupID) );
00647                 executeQuery("DELETE FROM ConnectionGroups WHERE NetworkID="+ QString::number(networkID) + " AND ConnectionGroupID=" + QString::number(conGroupID) );
00648                 ++numberOfCompletedSteps;
00649         }
00650 
00651         //Reset list
00652         connectionGroupIDList.clear();
00653 }
00654 
00655 
00658 void NetworkDaoThread::deleteNetwork(){
00659         numberOfCompletedSteps = 0;
00660         totalNumberOfSteps = 1;
00661         progressMessage = "Deleting network.";
00662         executeQuery("DELETE FROM Networks WHERE NetworkID = " + QString::number(networkID));
00663         networkID = 0;
00664         numberOfCompletedSteps = 1;
00665 }
00666 
00667 
00669 void NetworkDaoThread::deleteNeuronGroups(){
00670         numberOfCompletedSteps = 0;
00671         totalNumberOfSteps = neuronGroupIDList.size();
00672         progressMessage = "Deleting neuron groups";
00673 
00674         //Check that network id is valid
00675         if(networkID == 0){
00676                 setError("Network ID has not been set.");
00677                 return;
00678         }
00679 
00680         //Work through the list of neuron groups
00681         foreach(unsigned int neuronGroupID, neuronGroupIDList){
00682                 executeQuery("DELETE FROM Neurons WHERE NeuronGroupID=" + QString::number(neuronGroupID) );
00683                 executeQuery("DELETE FROM NeuronGroups WHERE NetworkID="+ QString::number(networkID) + " AND NeuronGroupID=" + QString::number(neuronGroupID) );
00684                 ++numberOfCompletedSteps;
00685         }
00686 
00687         //Reset list
00688         neuronGroupIDList.clear();
00689 }
00690 
00691 
00693 void NetworkDaoThread::loadConnections(){
00694         //Reset progress
00695         numberOfCompletedSteps = 0;
00696         totalNumberOfSteps = getConnectionCount(connectionGroupList);
00697 
00698     //Work through all the connections to be loaded
00699     for(QList<ConnectionGroup*>::iterator iter = connectionGroupList.begin(); iter != connectionGroupList.end(); ++iter){
00700 
00701                 //Empty current connections in group
00702                 (*iter)->clearConnections();
00703 
00704                 //Load connections into group
00705                 unsigned int tmpConGrpID = (*iter)->getID();
00706                 QSqlQuery query = getQuery("SELECT ConnectionID, FromNeuronID, ToNeuronID, Delay, Weight FROM Connections WHERE ConnectionGroupID = " + QString::number(tmpConGrpID));
00707                 executeQuery(query);
00708                 while ( query.next() ) {
00709                         (*iter)->addConnection(
00710                                         query.value(0).toUInt(),//ID
00711                                         query.value(1).toUInt(),//FromNeuronID
00712                                         query.value(2).toUInt(),//ToNeuronID
00713                                         query.value(3).toString().toFloat(),//Delay
00714                                         query.value(4).toString().toFloat()//Weight
00715                         );
00716 
00717                         //Track progress
00718                         ++numberOfCompletedSteps;
00719 
00720                         //Quit if user cancels
00721                         if(stopThread)
00722                                 return;
00723                 }
00724 
00725                 //Load parameters in connection group
00726                 QHash<QString, double> tmpParamMap = getSynapseParameters( (*iter)->getInfo());
00727                 (*iter)->setParameters(tmpParamMap);
00728     }
00729 }
00730 
00731 
00733 void NetworkDaoThread::loadNeurons(){
00734         //Reset progress measure
00735         numberOfCompletedSteps = 0;
00736         totalNumberOfSteps = getNeuronCount(neuronGroupList);
00737 
00738     //Work through all the neurons to be loaded
00739     for(QList<NeuronGroup*>::iterator iter = neuronGroupList.begin(); iter != neuronGroupList.end(); ++iter){
00740 
00741                 //Empty current connections in group
00742                 (*iter)->clearNeurons();
00743 
00744                 //Get pointer to neuron map
00745                 NeuronMap* tmpNeurMap = (*iter)->getNeuronMap();
00746 
00747                 //Load neurons into group
00748                 bool firstTime = true;
00749                 QSqlQuery query = getQuery("SELECT NeuronID, X, Y, Z FROM Neurons WHERE NeuronGroupID = " + QString::number((*iter)->getID()) + " ORDER BY NeuronID");
00750                 executeQuery(query);
00751                 while ( query.next() ) {
00752                         Neuron* tmpNeuron = new Neuron(
00753                                         query.value(0).toUInt(),//ID
00754                                         query.value(1).toString().toFloat(),//X
00755                                         query.value(2).toString().toFloat(),//Y
00756                                         query.value(3).toString().toFloat()//Z
00757                                         );
00758                         (*tmpNeurMap)[query.value(0).toUInt()] = tmpNeuron;
00759 
00760                         //Store the start neuron id - useful when neurons are stored continuously, which is usually but not always the case
00761                         if(firstTime){
00762                                 (*iter)->setStartNeuronID(query.value(0).toUInt());
00763                                 firstTime = false;
00764                         }
00765 
00766                         //Track progress
00767                         ++numberOfCompletedSteps;
00768 
00769                         //Quit if user cancels
00770                         if(stopThread)
00771                                 return;
00772                 }
00773 
00774                 //Load parameters in neuron group
00775                 QHash<QString, double> tmpParamMap = getNeuronParameters( (*iter)->getInfo());
00776                 (*iter)->setParameters(tmpParamMap);
00777     }
00778 }
00779 
00780 
00784 void NetworkDaoThread::setError(const QString& msg){
00785     errorMessage = msg;
00786     error = true;
00787     stopThread = true;
00788 }
00789 
00790 
00792 void NetworkDaoThread::saveNetwork(){
00793         #ifdef DEBUG
00794                 cout<<"Saving network."<<endl;
00795                 if(!neuronGroupIDList.isEmpty()){
00796                         cout<<"Deleting neuron groups with IDs: ";
00797                         foreach(unsigned int neuronGroupID, neuronGroupIDList){
00798                                 cout<<neuronGroupID<<" ";
00799                         }
00800                         cout<<endl;
00801                 }
00802                 if(!connectionGroupIDList.isEmpty()){
00803                         cout<<"Deleting connection groups with IDs: ";
00804                         foreach(unsigned int neuronGroupID, connectionGroupIDList){
00805                                 cout<<neuronGroupID<<" ";
00806                         }
00807                         cout<<endl;
00808                 }
00809                 if(!neuronGroupList.isEmpty()){
00810                         cout<<"Adding neuron groups with temporary IDs: ";
00811                         foreach(NeuronGroup* neuronGroup, neuronGroupList){
00812                                 cout<<neuronGroup->getID()<<" ";
00813                         }
00814                         cout<<endl;
00815                 }
00816                 if(!connectionGroupList.isEmpty()){
00817                         cout<<"Adding connection groups with temporary IDs: ";
00818                         foreach(ConnectionGroup* conGroup, connectionGroupList){
00819                                 cout<<conGroup->getID()<<" ";
00820                         }
00821                         cout<<endl;
00822                 }
00823         #endif//DEBUG
00824 
00825         progressMessage = "Saving network";
00826 
00827         //Delete neuron and connection groups that have been deleted from the prototype
00828         deleteNeuronGroups();
00829         deleteConnectionGroups();
00830 
00831         /* Store link between old IDs and neurons in the groups that we are going to add.
00832            Also store link between old neuron group IDs and neuron group IDs */
00833         QHash<unsigned, Neuron*> oldIDNeurMap;
00834         QHash<unsigned, NeuronGroup*> oldIDNeurGrpMap;
00835         foreach(NeuronGroup* tmpNeurGrp, neuronGroupList){
00836                 //Store old neuron group ID
00837                 oldIDNeurGrpMap[tmpNeurGrp->getID()] = tmpNeurGrp;
00838 
00839                 //Store old neuron IDS
00840                 QHash<unsigned, Neuron*>::iterator endNeurGrp = tmpNeurGrp->end();
00841                 for(QHash<unsigned, Neuron*>::iterator neurIter = tmpNeurGrp->begin(); neurIter != endNeurGrp; ++neurIter){
00842                         oldIDNeurMap[neurIter.key()] = neurIter.value();
00843                 }
00844         }
00845 
00846         //Add neuron groups to database, the new IDs wil be stored in the neurons and neuron groups
00847         addNeuronGroups();
00848 
00849         //Update connections with the new IDs
00850         foreach(ConnectionGroup* tmpConGrp, connectionGroupList){
00851                 //Update FROM neuron group ID and FROM neuron IDs
00852                 if(oldIDNeurGrpMap.contains(tmpConGrp->getFromNeuronGroupID())){
00853                         tmpConGrp->setFromNeuronGroupID(oldIDNeurGrpMap[tmpConGrp->getFromNeuronGroupID()]->getID());
00854                         ConnectionIterator endConGrp = tmpConGrp->end();
00855                         for(ConnectionIterator conIter = tmpConGrp->begin(); conIter!= endConGrp; ++conIter){
00856                                 //Check FROM neuron ID exists
00857                                 if(oldIDNeurMap.contains(conIter->getFromNeuronID()))
00858                                         conIter->setFromNeuronID(oldIDNeurMap[conIter->getFromNeuronID()]->getID());
00859                                 else
00860                                         throw SpikeStreamException("FROM neuron ID missing from old ID neuron map: " + QString::number(conIter->getFromNeuronID()));
00861                         }
00862                 }
00863                 //Update TO neuron group ID and TO neuron IDs
00864                 if(oldIDNeurGrpMap.contains(tmpConGrp->getToNeuronGroupID())){
00865                         tmpConGrp->setToNeuronGroupID(oldIDNeurGrpMap[tmpConGrp->getToNeuronGroupID()]->getID());
00866                         ConnectionIterator endConGrp = tmpConGrp->end();
00867                         for(ConnectionIterator conIter = tmpConGrp->begin(); conIter!= endConGrp; ++conIter){
00868                                 //Check TO neuron ID exists
00869                                 if(oldIDNeurMap.contains(conIter->getToNeuronID()))
00870                                         conIter->setToNeuronID(oldIDNeurMap[conIter->getToNeuronID()]->getID());
00871                                 else
00872                                         throw SpikeStreamException("TO neuron ID missing from old ID neuron map: " + QString::number(conIter->getToNeuronID()));
00873                         }
00874                 }
00875         }
00876 
00877         //Add connection groups to the database, the new IDs will be stored in the connection groups
00878         addConnectionGroups();
00879 
00880         //Store volatile connection groups
00881         saveTempWeights();
00882 }
00883 
00884 
00886 void NetworkDaoThread::saveTempWeights(){
00887         //Reset progress measure
00888         numberOfCompletedSteps = 0;
00889         progressMessage = "Saving temporary weights";
00890 
00891         //Calculate number of steps
00892         for(QList<ConnectionGroup*>::iterator conGrpIter = volatileConnectionGroupList.begin(); conGrpIter != volatileConnectionGroupList.end() && !stopThread; ++conGrpIter)
00893                 totalNumberOfSteps += (*conGrpIter)->size();
00894 
00895         //Work through the list of connection groups
00896         for(QList<ConnectionGroup*>::iterator conGrpIter = volatileConnectionGroupList.begin(); conGrpIter != volatileConnectionGroupList.end() && !stopThread; ++conGrpIter){
00897                 //Get a pointer to the connection group
00898                 ConnectionGroup* tmpConGrp = *conGrpIter;
00899 
00900                 #ifdef TIME_PERFORMANCE
00901                         PerformanceTimer timer;
00902                 #endif//TIME_PERFORMANCE
00903 
00904                 //Build query
00905                 QSqlQuery query = getQuery();
00906                 QString queryStr;
00907                 for(int i=0; i<numConBuffers; ++i)
00908                         queryStr += "UPDATE Connections SET Weight= ? WHERE ConnectionID = ?;";
00909                 query.prepare(queryStr);
00910 
00911                 //Work through the connections
00912                 int conCntr = 0, offset = 0, conAddedCntr = 0;
00913                 QList<Connection*> tmpConList;
00914                 ConnectionIterator endConGrp = tmpConGrp->end();
00915                 for(ConnectionIterator conIter = tmpConGrp->begin(); conIter != endConGrp && !stopThread; ++conIter){
00916                         offset = 2 * (conCntr % numConBuffers);
00917 
00918                         //Bind values to query
00919                         tmpConList.append(&(*conIter));
00920                         query.bindValue(0 + offset, conIter->getTempWeight());
00921                         query.bindValue(1 + offset, conIter->getID());
00922 
00923                         //Execute query
00924                         if(conCntr % numConBuffers == numConBuffers-1){
00925                                 executeQuery(query);
00926 
00927                                 //Count number of connections that have been added
00928                                 conAddedCntr += numConBuffers;
00929                                 numberOfCompletedSteps = conAddedCntr;
00930 
00931                                 //Clear up list
00932                                 tmpConList.clear();
00933                         }
00934 
00935                         //Keep track of the number of connections
00936                         ++conCntr;
00937                 }
00938 
00939                 //Add remaining connections individually
00940                 if(!tmpConList.isEmpty() && !stopThread){
00941                         query = getQuery();
00942                         query.prepare("UPDATE Connections SET Weight= ? WHERE ConnectionID = ?");
00943                         for(QList<Connection*>::iterator conIter = tmpConList.begin(); conIter != tmpConList.end(); ++conIter){
00944                                 query.bindValue(0, (*conIter)->getTempWeight());
00945                                 query.bindValue(1, (*conIter)->getID());
00946 
00947                                 //Execute query
00948                                 executeQuery(query);
00949 
00950                                 //Count number of connections that have been added
00951                                 ++conAddedCntr;
00952                                 numberOfCompletedSteps = conAddedCntr;
00953                         }
00954                 }
00955 
00956                 //Check that we have added all the connections
00957                 if(!stopThread && (tmpConGrp->size() != conAddedCntr) )
00958                         throw SpikeStreamException("Number of connections added to database: " + QString::number(conAddedCntr) + " does not match size of connection group: " + QString::number(tmpConGrp->size()));
00959 
00960                 #ifdef TIME_PERFORMANCE
00961                         timer.printTime("Number of buffers: " + QString::number(numConBuffers) + ". Number of connections remaining: " + QString::number(tmpConList.size()) + ". Adding " + QString::number(conCntr) + " connections");
00962                 #endif//TIME_PERFORMANCE
00963         }
00964 
00965         //Clean up
00966         volatileConnectionGroupList.clear();
00967 }
00968 
 All Classes Files Functions Variables Typedefs Defines