SpikeStream Library  0.2
Network.cpp
Go to the documentation of this file.
00001 //SpikeStream includes
00002 #include "GlobalVariables.h"
00003 #include "Network.h"
00004 #include "SpikeStreamException.h"
00005 using namespace spikestream;
00006 
00007 //Other includes
00008 #include <iostream>
00009 using namespace std;
00010 
00011 //Outputs memory debugging information
00012 //#define MEMORY_DEBUG
00013 
00015 Network::Network(const QString& name, const QString& description, const DBInfo& networkDBInfo, const DBInfo& archiveDBInfo){
00016     //Store information
00017         this->setObjectName(name);
00018     this->info.setName(name);
00019     this->info.setDescription(description);
00020         this->networkDBInfo = networkDBInfo;
00021         this->archiveDBInfo = archiveDBInfo;
00022 
00023     //Create network dao threads for heavy operations
00024         neuronNetworkDaoThread = new NetworkDaoThread(networkDBInfo, "neurNetDao1");
00025     connect (neuronNetworkDaoThread, SIGNAL(finished()), this, SLOT(neuronThreadFinished()));
00026         connectionNetworkDaoThread = new NetworkDaoThread(networkDBInfo, "conNetDao1");
00027     connect (connectionNetworkDaoThread, SIGNAL(finished()), this, SLOT(connectionThreadFinished()));
00028 
00029     //Initialize variables
00030         initializeVariables();
00031 
00032     //Create new network in database. ID will be stored in the network info
00033         NetworkDao networkDao(networkDBInfo);
00034         networkDao.addNetwork(info);
00035 }
00036 
00037 
00039 Network::Network(const NetworkInfo& networkInfo, const DBInfo& networkDBInfo, const DBInfo& archiveDBInfo){
00040     //Store information
00041         this->setObjectName(info.getName());
00042     this->info = networkInfo;
00043         this->networkDBInfo = networkDBInfo;
00044         this->archiveDBInfo = archiveDBInfo;
00045 
00046     //Check that network ID is valid
00047     if(info.getID() == INVALID_NETWORK_ID){
00048                 throw SpikeStreamException ("Attempting to load an invalid network");
00049     }
00050 
00051     //Create network dao threads for heavy operations
00052         neuronNetworkDaoThread = new NetworkDaoThread(networkDBInfo, "neurNetDao2");
00053     connect (neuronNetworkDaoThread, SIGNAL(finished()), this, SLOT(neuronThreadFinished()));
00054         connectionNetworkDaoThread = new NetworkDaoThread(networkDBInfo, "conNetDao2");
00055     connect (connectionNetworkDaoThread, SIGNAL(finished()), this, SLOT(connectionThreadFinished()));
00056 
00057     //Initialize variables
00058         initializeVariables();
00059 }
00060 
00061 
00063 Network::~Network(){
00064         #ifdef MEMORY_DEBUG
00065                 cout<<"Deleting network"<<endl;
00066         #endif//MEMORY_DEBUG
00067 
00068     if(neuronNetworkDaoThread != NULL){
00069                 neuronNetworkDaoThread->stop();
00070                 neuronNetworkDaoThread->wait();
00071                 delete neuronNetworkDaoThread;
00072     }
00073     if(connectionNetworkDaoThread != NULL){
00074                 connectionNetworkDaoThread->stop();
00075                 connectionNetworkDaoThread->wait();
00076                 delete connectionNetworkDaoThread;
00077     }
00078 
00079     //Empties all data stored in the class
00080         clearConnectionGroups();
00081         clearNeuronGroups();
00082 }
00083 
00084 
00085 
00086 /*--------------------------------------------------------- */
00087 /*-----                PUBLIC METHODS                 ----- */
00088 /*--------------------------------------------------------- */
00089 
00091 void Network::addConnectionGroups(QList<ConnectionGroup*>& connectionGroupList){
00092         //Clear variables
00093         connectionTaskCancelled = false;
00094 
00095         //Check if network is editable or not
00096         if(!prototypeMode && hasArchives())
00097                 throw SpikeStreamException("Cannot add connection groups to a locked network.");
00098 
00099         //Set default parameters
00100         NetworkDao netDao(networkDBInfo);
00101         foreach(ConnectionGroup* conGrp, connectionGroupList){
00102                 if(!conGrp->parametersSet()){
00103                         QHash<QString, double> tmpParamMap = netDao.getDefaultSynapseParameters(conGrp->getSynapseTypeID());
00104                         conGrp->setParameters(tmpParamMap);
00105                 }
00106         }
00107 
00108         //In prototype mode, we add connection groups to network and store them in a list for later
00109         if(prototypeMode){
00110                 foreach(ConnectionGroup* conGrp, connectionGroupList){
00111                         unsigned tmpID = getTemporaryConGrpID();//Get an ID for the connection groups
00112                         conGrp->setID(tmpID);//Set ID in connection group
00113                         connGrpMap[tmpID] = conGrp;//Add connection group to network
00114                         newConnectionGroupMap[tmpID] = conGrp;//Store connection group in map for adding to database later
00115                         #ifdef MEMORY_DEBUG
00116                                 cout<<"Network size: "<<sizeof(*this)<<"; adding connection group with memory size: "<<sizeof(*conGrp);
00117                                 cout<<"; size of 1 connection: "<<sizeof(*conGrp->begin())<<endl;
00118                         #endif//MEMORY_DEBUG
00119                 }
00120         }
00121         //In normal mode, connection groups are saved immediately to the database
00122         else{
00123                 //Store the connection groups to be added in the map with ids increasing from 1
00124                 newConnectionGroupMap.clear();
00125                 for(int i=0; i<connectionGroupList.size(); ++i)
00126                         newConnectionGroupMap[i+1] = connectionGroupList.at(i);
00127 
00128                 //Start thread that adds connection groups to database
00129                 startAddConnectionGroups();
00130         }
00131 }
00132 
00133 
00135 void Network::addNeuronGroups(QList<NeuronGroup*>& neuronGroupList){
00136         //Reset variables
00137         neuronTaskCancelled = false;
00138 
00139         //Check if network is editable or not
00140         if(!prototypeMode && hasArchives())
00141                 throw SpikeStreamException("Cannot add neuron groups to a locked network.");
00142 
00143         //Set default parameters
00144         NetworkDao netDao(networkDBInfo);
00145         foreach(NeuronGroup* neurGrp, neuronGroupList){
00146                 if(!neurGrp->parametersSet()){
00147                         QHash<QString, double> tmpParamMap = netDao.getDefaultNeuronParameters(neurGrp->getNeuronTypeID());
00148                         neurGrp->setParameters(tmpParamMap);
00149                 }
00150         }
00151 
00152         //In prototype mode, we add connection groups to network and store them in a list for later
00153         if(prototypeMode){
00154                 foreach(NeuronGroup* neurGrp, neuronGroupList){
00155                         unsigned tmpID = getTemporaryNeurGrpID();//Get an ID for the neuron group
00156                         neurGrp->setID(tmpID);//Set ID in neuron group
00157                         neurGrpMap[tmpID] = neurGrp;//Add neuron group to network
00158                         newNeuronGroupMap[tmpID] = neurGrp;//Store neuron group in map for adding to database later
00159                 }
00160         }
00161         //In normal mode, neuron groups are saved immediately to the database
00162         else{
00163                 //Store the neuron groups to be added in the map with ids increasing from 1
00164                 newNeuronGroupMap.clear();
00165                 for(int i=0; i<neuronGroupList.size(); ++i)
00166                         newNeuronGroupMap[i+1] = neuronGroupList.at(i);
00167 
00168                 //Start thread to add neuron groups to database
00169                 startAddNeuronGroups();
00170         }
00171 }
00172 
00173 
00176 void Network::cancel(){
00177         if(connectionNetworkDaoThread->isRunning()){
00178                 connectionNetworkDaoThread->stop();
00179                 connectionTaskCancelled = true;
00180         }
00181         if(neuronNetworkDaoThread->isRunning()){
00182                 neuronNetworkDaoThread->stop();
00183                 neuronTaskCancelled = true;
00184         }
00185 }
00186 
00187 
00189 void Network::clearError(){
00190         error = false;
00191         errorMessage = "";
00192 }
00193 
00194 
00196 bool Network::containsNeuron(unsigned int neurID){
00197     //Need to check each neuron group to see if it contains the neuron.
00198     for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter){
00199                 if(iter.value()->contains(neurID)){
00200                         return true;
00201                 }
00202     }
00203     return false;
00204 }
00205 
00206 
00208 bool Network::containsNeuronGroup(unsigned int neuronGroupID){
00209         if(neurGrpMap.contains(neuronGroupID))
00210                 return true;
00211         return false;
00212 }
00213 
00214 
00216 void Network::copyTempWeightsToWeights(unsigned conGrpID){
00217         //Copy temp weight into weight
00218         ConnectionGroup* tmpConGrp = getConnectionGroup(conGrpID);
00219         ConnectionIterator endConGrp = tmpConGrp->end();
00220         for(ConnectionIterator iter = tmpConGrp->begin(); iter != endConGrp; ++iter){
00221                 iter->setWeight(iter->getTempWeight());
00222         }
00223 
00224         //Put network into prototype mode
00225         prototypeMode = true;
00226 
00227         //Record that connection group has unsaved weights
00228         if(!newConnectionGroupMap.contains(conGrpID))
00229                 volatileConnectionGroupMap[conGrpID] = true;
00230 }
00231 
00232 
00235 void Network::deleteConnectionGroups(QList<unsigned>& deleteConGrpIDList){
00236         //Check if network is editable or not
00237         if(!prototypeMode && hasArchives())
00238                 throw SpikeStreamException("Cannot delete connection groups from a locked network.");
00239 
00240         //Check that network is not currently busy with some other task
00241         if(connectionNetworkDaoThread->isRunning())
00242                 throw SpikeStreamException("Network is busy with another connection-related task.");
00243 
00244         //Check that connection group ids exist in network
00245         foreach(unsigned int conGrpID, deleteConGrpIDList){
00246                 if(!connGrpMap.contains(conGrpID))
00247                         throw SpikeStreamException("Connection group ID " + QString::number(conGrpID) + " cannot be found in the current network.");
00248         }
00249 
00250         //Remove connection groups from memory
00251         foreach(unsigned conGrpID, deleteConGrpIDList){
00252                 deleteConnectionGroupFromMemory(conGrpID);
00253         }
00254 
00255         if(prototypeMode){
00256                 if(!isBusy())
00257                         emit taskFinished();//Inform listening classes that deletion is complete
00258                 else
00259                         throw SpikeStreamException("Network is busy when deleting connection groups - it should not be engaged in other tasks.");
00260         }
00261         else{
00262                 startDeleteConnectionGroups(deleteConGrpIDList);
00263         }
00264 }
00265 
00266 
00269 void Network::deleteNeuronGroups(QList<unsigned int>& deleteNeurGrpIDList){
00270         //Check if network is editable or not
00271         if(hasArchives())
00272                 throw SpikeStreamException("Cannot delete neuron groups from a locked network.");
00273 
00274         //Check that network is not currently busy with some other task
00275         if(neuronNetworkDaoThread->isRunning())
00276                 throw SpikeStreamException("Network is busy with another neuron-related task.");
00277 
00278         //Check that neuron group ids exist in network
00279         foreach(unsigned int neurGrpID, deleteNeurGrpIDList){
00280                 if(!neurGrpMap.contains(neurGrpID))
00281                         throw SpikeStreamException("Neuron group ID " + QString::number(neurGrpID) + " cannot be found in the current network.");
00282         }
00283 
00284         foreach(unsigned neurGrpID, deleteNeurGrpIDList){
00285                 //Remove neuron groups from memory along with their associated connections
00286                 deleteNeuronGroupFromMemory(neurGrpID);
00287         }
00288 
00289         if(prototypeMode){
00290                 if(!isBusy())
00291                         emit taskFinished();//Inform listening classes that deletion is complete
00292                 else
00293                         throw SpikeStreamException("Network is busy when deleting neuron groups - it should not be engaged in other tasks.");
00294         }
00295         else{
00296                 startDeleteNeuronGroups(deleteNeurGrpIDList);
00297         }
00298 }
00299 
00300 
00303 int Network::getConnectionCount(unsigned conGrpID){
00304         if(!connGrpMap.contains(conGrpID))
00305                 throw SpikeStreamException("Error getting connection count. Connection group with the specified ID does not exist in this network.");
00306         return connGrpMap[conGrpID]->size();
00307 }
00308 
00309 
00311 QList<ConnectionGroup*> Network::getConnectionGroups(){
00312         QList<ConnectionGroup*> tmpList;
00313         for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter)
00314                 tmpList.append(iter.value());
00315         return tmpList;
00316 }
00317 
00318 
00320 QList<ConnectionGroupInfo> Network::getConnectionGroupsInfo(){
00321     QList<ConnectionGroupInfo> tmpList;
00322     for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter)
00323                 tmpList.append(iter.value()->getInfo());
00324     return tmpList;
00325 }
00326 
00327 
00329 QList<ConnectionGroupInfo> Network::getConnectionGroupsInfo(unsigned int synapseTypeID){
00330         QList<ConnectionGroupInfo> tmpList;
00331         for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter){
00332                 if(iter.value()->getInfo().getSynapseTypeID() == synapseTypeID)
00333                         tmpList.append(iter.value()->getInfo());
00334         }
00335         return tmpList;
00336 }
00337 
00338 
00341 NeuronGroup* Network::getNeuronGroupFromNeuronID(unsigned neuronID){
00342         //Need to check each neuron group to see if it contains the neuron.
00343         for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter){
00344                 if(iter.value()->contains(neuronID)){
00345                         return iter.value();
00346                 }
00347         }
00348         throw SpikeStreamException("Neuron group containing neuron with id " + QString::number(neuronID) + " cannot be found.");
00349 }
00350 
00351 
00353 QList<NeuronGroup*> Network::getNeuronGroups(){
00354         QList<NeuronGroup*> tmpList;
00355         for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter)
00356                 tmpList.append(iter.value());
00357         return tmpList;
00358 }
00359 
00360 
00362 QList<NeuronGroupInfo> Network::getNeuronGroupsInfo(){
00363     QList<NeuronGroupInfo> tmpList;
00364     for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter)
00365                 tmpList.append(iter.value()->getInfo());
00366     return tmpList;
00367 }
00368 
00369 
00371 QList<NeuronGroupInfo> Network::getNeuronGroupsInfo(unsigned int neuronTypeID){
00372         QList<NeuronGroupInfo> tmpList;
00373         for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter){
00374                 if(iter.value()->getInfo().getNeuronTypeID() == neuronTypeID)
00375                         tmpList.append(iter.value()->getInfo());
00376         }
00377         return tmpList;
00378 }
00379 
00380 
00382 bool Network::isBusy() {
00383     if(neuronNetworkDaoThread->isRunning() || connectionNetworkDaoThread->isRunning())
00384                 return true;
00385     return false;
00386 }
00387 
00388 
00390 QList<unsigned int> Network::getNeuronGroupIDs(){
00391     return neurGrpMap.keys();
00392 }
00393 
00394 
00396 QList<unsigned int> Network::getConnectionGroupIDs(){
00397     return connGrpMap.keys();
00398 }
00399 
00400 
00402 Box Network::getBoundingBox(){
00403     /* Neurons are not directly linked with a neuron id, so need to work through
00404        each neuron group and create a box that includes all the other boxes. */
00405     Box networkBox;
00406     bool firstTime = true;
00407     QList<NeuronGroup*> tmpNeurGrpList = neurGrpMap.values();
00408     for(QList<NeuronGroup*>::iterator iter = tmpNeurGrpList.begin(); iter != tmpNeurGrpList.end(); ++iter){
00409                 if(firstTime){//Take box enclosing first neuron group as a starting point
00410                         networkBox = (*iter)->getBoundingBox();
00411                         firstTime = false;
00412                 }
00413                 else{//Expand box to include subsequent neuron groups
00414                         Box neurGrpBox = (*iter)->getBoundingBox();
00415                         if(neurGrpBox.x1 < networkBox.x1)
00416                                 networkBox.x1 = neurGrpBox.x1;
00417                         if(neurGrpBox.y1 < networkBox.y1)
00418                                 networkBox.y1 = neurGrpBox.y1;
00419                         if(neurGrpBox.z1 < networkBox.z1)
00420                                 networkBox.z1 = neurGrpBox.z1;
00421 
00422                         if(neurGrpBox.x2 > networkBox.x2)
00423                                 networkBox.x2 = neurGrpBox.x2;
00424                         if(neurGrpBox.y2 > networkBox.y2)
00425                                 networkBox.y2 = neurGrpBox.y2;
00426                         if(neurGrpBox.z2 > networkBox.z2)
00427                                 networkBox.z2 = neurGrpBox.z2;
00428                 }
00429     }
00430     return networkBox;
00431 }
00432 
00433 
00435 bool Network::overlaps(const Box& box){
00436         QList<NeuronGroup*> tmpNeurGrpList = neurGrpMap.values();
00437         for(QList<NeuronGroup*>::iterator iter = tmpNeurGrpList.begin(); iter != tmpNeurGrpList.end(); ++iter){
00438                 if( (*iter)->getBoundingBox().intersects(box) )
00439                         return true;
00440         }
00441         return false;
00442 }
00443 
00444 
00446 Box Network::getNeuronGroupBoundingBox(unsigned int neurGrpID){
00447         return getNeuronGroup(neurGrpID)->getBoundingBox();
00448 }
00449 
00450 
00454 NeuronGroup* Network::getNeuronGroup(unsigned int id){
00455     checkNeuronGroupID(id);
00456     return neurGrpMap[id];
00457 }
00458 
00459 
00461 NeuronGroupInfo Network::getNeuronGroupInfo(unsigned int id){
00462     checkNeuronGroupID(id);
00463     return neurGrpMap[id]->getInfo();
00464 }
00465 
00466 
00469 ConnectionGroup* Network::getConnectionGroup(unsigned int id){
00470     checkConnectionGroupID(id);
00471     return connGrpMap[id];
00472 }
00473 
00474 
00476 ConnectionGroupInfo Network::getConnectionGroupInfo(unsigned int id){
00477     checkConnectionGroupID(id);
00478     return connGrpMap[id]->getInfo();
00479 }
00480 
00481 
00483 QString Network::getErrorMessage(){
00484         return errorMessage;
00485 }
00486 
00487 
00489 int Network::getNumberOfCompletedSteps(){
00490         int numSteps = 0;
00491         if(neuronNetworkDaoThread->isRunning())
00492                 numSteps += neuronNetworkDaoThread->getNumberOfCompletedSteps();
00493         if(connectionNetworkDaoThread->isRunning())
00494                 numSteps += connectionNetworkDaoThread->getNumberOfCompletedSteps();
00495         return numSteps;
00496 }
00497 
00498 
00500 int Network::getTotalNumberOfSteps(){
00501         int total = 0;
00502         if(neuronNetworkDaoThread->isRunning())
00503                 total += neuronNetworkDaoThread->getTotalNumberOfSteps();
00504         if(connectionNetworkDaoThread->isRunning())
00505                 total += connectionNetworkDaoThread->getTotalNumberOfSteps();
00506         return total;
00507 }
00508 
00509 
00511 QString Network::getProgressMessage(){
00512         if(neuronNetworkDaoThread->isRunning() && connectionNetworkDaoThread->isRunning())
00513                 return neuronNetworkDaoThread->getProgressMessage() + "; " + connectionNetworkDaoThread->getProgressMessage();
00514         else if (neuronNetworkDaoThread->isRunning())
00515                 return neuronNetworkDaoThread->getProgressMessage();
00516         else if (connectionNetworkDaoThread->isRunning())
00517                 return connectionNetworkDaoThread->getProgressMessage();
00518         else
00519                 return progressMessage;
00520 }
00521 
00522 
00524 bool Network::hasArchives(){
00525         ArchiveDao archiveDao(archiveDBInfo);
00526         return archiveDao.networkHasArchives(getID());
00527 }
00528 
00529 
00531 bool Network::isSaved(){
00532         if(prototypeMode){
00533                 if(!newConnectionGroupMap.isEmpty())
00534                         return false;
00535                 if(!newNeuronGroupMap.isEmpty())
00536                         return false;
00537                 if(!deleteNeuronGroupIDs.isEmpty())
00538                         return false;
00539                 if(!deleteConnectionGroupIDs.isEmpty())
00540                         return false;
00541                 if(neuronGroupParametersChanged || connectionGroupParametersChanged)
00542                         return false;
00543                 if(!volatileConnectionGroupMap.isEmpty())
00544                         return false;
00545         }
00546         return true;
00547 }
00548 
00549 
00551 void Network::load(){
00552     clearError();
00553         progressMessage = "Loading network...";
00554 
00555         //Load up basic information about the neuron and connection groups
00556         loadNeuronGroupsInfo();
00557         loadConnectionGroupsInfo();
00558 
00559         //Load up all neurons
00560         neuronNetworkDaoThread->prepareLoadNeurons(neurGrpMap.values());
00561         currentNeuronTask = LOAD_NEURONS_TASK;
00562         neuronNetworkDaoThread->start();
00563 
00564         //Load all connection groups
00565         connectionNetworkDaoThread->prepareLoadConnections(connGrpMap.values());
00566         currentConnectionTask = LOAD_CONNECTIONS_TASK;
00567         connectionNetworkDaoThread->start();
00568 }
00569 
00570 
00571 
00574 void Network::loadWait(){
00575         clearError();
00576 
00577         //Load up basic information about the neuron and connection groups
00578         loadNeuronGroupsInfo();
00579         loadConnectionGroupsInfo();
00580 
00581         //Load up all neurons
00582         neuronNetworkDaoThread->prepareLoadNeurons(neurGrpMap.values());
00583         currentNeuronTask = LOAD_NEURONS_TASK;
00584         neuronNetworkDaoThread->start();
00585         neuronNetworkDaoThread->wait();
00586         neuronThreadFinished();
00587 
00588         //Load all connection groups
00589         connectionNetworkDaoThread->prepareLoadConnections(connGrpMap.values());
00590         currentConnectionTask = LOAD_CONNECTIONS_TASK;
00591         connectionNetworkDaoThread->start();
00592         connectionNetworkDaoThread->wait();
00593         connectionThreadFinished();
00594 }
00595 
00596 
00599 void Network::save(){
00600         if(!prototypeMode)
00601                 throw SpikeStreamException("Network should not be saved unless it is in prototype mode.");
00602 
00603         //Get the volatile connection groups
00604         QList<ConnectionGroup*> tmpVolConGrpList;
00605         for(QHash<unsigned,bool>::iterator iter = volatileConnectionGroupMap.begin(); iter != volatileConnectionGroupMap.end(); ++iter)
00606                 tmpVolConGrpList.append(getConnectionGroup(iter.key()));
00607 
00608         //Remove connection and neuron groups from network - they will be added later with the correct IDs.
00609         for(QHash<unsigned, ConnectionGroup*>::iterator iter = newConnectionGroupMap.begin(); iter != newConnectionGroupMap.end(); ++iter)
00610                 connGrpMap.remove(iter.value()->getID());
00611         for(QHash<unsigned, NeuronGroup*>::iterator iter = newNeuronGroupMap.begin(); iter != newNeuronGroupMap.end(); ++iter)
00612                 neurGrpMap.remove(iter.value()->getID());
00613 
00614         //Start thread to add/delete from database and get appropriate IDs inside the classes.
00615         currentNeuronTask = SAVE_NETWORK_TASK;
00616         neuronNetworkDaoThread->startSaveNetwork(getID(),
00617                         newNeuronGroupMap.values(), newConnectionGroupMap.values(),
00618                         deleteNeuronGroupIDs, deleteConnectionGroupIDs, tmpVolConGrpList
00619         );
00620 
00621         //Store parameters in already saved neuron groups
00622         if(neuronGroupParametersChanged){
00623                 NetworkDao netDao(networkDBInfo);
00624                 for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter){
00625                         QHash<QString, double> tmpParamMap = iter.value()->getParameters();
00626                         netDao.setNeuronParameters(iter.value()->getInfo(), tmpParamMap);
00627                 }
00628                 neuronGroupParametersChanged = false;
00629         }
00630 
00631         //Store parameters in already saved connection groups
00632         if(connectionGroupParametersChanged){
00633                 NetworkDao netDao(networkDBInfo);
00634                 for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter){
00635                         QHash<QString, double> tmpParamMap = iter.value()->getParameters();
00636                         netDao.setSynapseParameters(iter.value()->getInfo(), tmpParamMap);
00637                 }
00638                 connectionGroupParametersChanged = false;
00639         }
00640 }
00641 
00642 
00645 void Network::setConnectionGroupProperties(unsigned conGrpID, const QString& description){
00646         if(!connGrpMap.contains(conGrpID))
00647                 throw SpikeStreamException("Connection group cannot be found: " + QString::number(conGrpID));
00648         connGrpMap[conGrpID]->setDescription(description);
00649 
00650         //Store in database if connection group is in database
00651         if(!newConnectionGroupMap.contains(conGrpID)){
00652                 NetworkDao netDao(networkDBInfo);
00653                 netDao.setConnectionGroupProperties(conGrpID, description);
00654         }
00655 }
00656 
00657 
00659 void Network::setNeuronGroupParameters(unsigned neurGrpID, QHash<QString, double> paramMap){
00660         //Set the parameters in memory
00661         NeuronGroup* tmpNeurGrp = getNeuronGroup(neurGrpID);
00662         tmpNeurGrp->setParameters(paramMap);
00663 
00664         //Store parameters in the database if we are not in prototype mode
00665         if(!prototypeMode){
00666                 NetworkDao netDao(networkDBInfo);
00667                 netDao.setNeuronParameters(tmpNeurGrp->getInfo(), paramMap);
00668         }
00669         else{
00670                 //Record fact that parameters have been changed if the neuron group is on disk
00671                 if(!newNeuronGroupMap.contains(neurGrpID))
00672                         neuronGroupParametersChanged = true;
00673         }
00674 }
00675 
00676 
00679 void Network::setNeuronGroupProperties(unsigned neurGrpID, const QString& name, const QString& description){
00680         if(!neurGrpMap.contains(neurGrpID))
00681                 throw SpikeStreamException("Neuron group cannot be found: " + QString::number(neurGrpID));
00682         neurGrpMap[neurGrpID]->setDescription(description);
00683         neurGrpMap[neurGrpID]->setName(name);
00684 
00685         //Store in database if we are not in prototype mode
00686         if(!newNeuronGroupMap.contains(neurGrpID)){
00687                 NetworkDao netDao(networkDBInfo);
00688                 netDao.setNeuronGroupProperties(neurGrpID, name, description);
00689         }
00690 }
00691 
00692 
00694 void Network::setPrototypeMode(bool mode){
00695         prototypeMode = mode;
00696 }
00697 
00698 
00699 /*--------------------------------------------------------- */
00700 /*-----                  PRIVATE SLOTS                ----- */
00701 /*--------------------------------------------------------- */
00702 
00704 void Network::connectionThreadFinished(){
00705     if(connectionNetworkDaoThread->isError()){
00706                 setError("Connection Loading Error: '" + connectionNetworkDaoThread->getErrorMessage() + "'. ");
00707     }
00708         if(!error){
00709                 try{
00710                         switch(currentConnectionTask){
00711                                 case ADD_CONNECTIONS_TASK:
00712                                         updateConnectionGroupsAfterSave();
00713                                 break;
00714                                 case DELETE_CONNECTIONS_TASK:
00715                                         ;
00716                                 break;
00717                                 case LOAD_CONNECTIONS_TASK:
00718                                         ;//Nothing to do at present
00719                                 break;
00720                                 default:
00721                                         throw SpikeStreamException("The current task ID has not been recognized.");
00722                         }
00723                 }
00724                 catch(SpikeStreamException& ex){
00725                         setError("End connection thread error " + ex.getMessage());
00726                 }
00727         }
00728 
00729     //Reset task
00730     currentConnectionTask = -1;
00731 
00732         //Emit signal that task has finished if no other threads are carrying out operations
00733         if(!neuronNetworkDaoThread->isRunning())
00734                 emit taskFinished();
00735 }
00736 
00737 
00739 void Network::neuronThreadFinished(){
00740     //Check for errors
00741     if(neuronNetworkDaoThread->isError()){
00742                 setError(neuronNetworkDaoThread->getErrorMessage() + "'. ");
00743     }
00744 
00745     //Handle any task-specific stuff
00746     if(!error){
00747                 try{
00748                         switch(currentNeuronTask){
00749                                 case ADD_NEURONS_TASK:
00750                                         updateNeuronGroupsAfterSave();
00751                                 break;
00752                                 case DELETE_NEURONS_TASK:
00753                                         ;
00754                                 break;
00755                                 case LOAD_NEURONS_TASK:
00756                                         ;//Nothing to do at present
00757                                 break;
00758                                 case SAVE_NETWORK_TASK:
00759                                         //Make IDs in memory match IDs in database
00760                                         updateNeuronGroupsAfterSave();
00761                                         updateConnectionGroupsAfterSave();
00762 
00763                                         //Remove IDs of neuron and connetion groups scheduled for deletion
00764                                         deleteNeuronGroupIDs.clear();
00765                                         deleteConnectionGroupIDs.clear();
00766 
00767                                         //Clean up volatile connection groups
00768                                         volatileConnectionGroupMap.clear();
00769 
00770                                         //Switch off transient mode in the network
00771                                         transient = false;
00772                                 break;
00773                                 default:
00774                                         throw SpikeStreamException("The current task ID has not been recognized.");
00775                         }
00776                 }
00777                 catch(SpikeStreamException& ex){
00778                         setError("End neuron thread error: " + ex.getMessage());
00779                 }
00780     }
00781 
00782     //Reset task
00783     currentNeuronTask = -1;
00784 
00785     //Emit signal that task has finished if no other threads are carrying out operations
00786         if(!connectionNetworkDaoThread->isRunning())
00787                 emit taskFinished();
00788 }
00789 
00790 
00793 int Network::size(){
00794         if(this->isBusy())
00795                 throw SpikeStreamException("Size of network cannot be determined while network is busy.");
00796 
00797         int neurCnt = 0;
00798         for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter)
00799                 neurCnt += iter.value()->size();
00800         return neurCnt;
00801 }
00802 
00803 
00804 /*--------------------------------------------------------- */
00805 /*-----                PRIVATE METHODS                ----- */
00806 /*--------------------------------------------------------- */
00807 
00810 void Network::checkConnectionGroupID(unsigned int id){
00811     if(!connGrpMap.contains(id))
00812                 throw SpikeStreamException(QString("Connection group with id ") + QString::number(id) + " is not in network with id " + QString::number(getID()));
00813 }
00814 
00815 
00818 void Network::checkNeuronGroupID(unsigned int id){
00819     if(!neurGrpMap.contains(id))
00820                 throw SpikeStreamException(QString("Neuron group with id ") + QString::number(id) + " is not in network with id " + QString::number(getID()));
00821 }
00822 
00823 
00825 void Network::deleteConnectionGroupFromMemory(unsigned conGrpID){
00826         //Remove connection group from map of new groups that only exist in memory
00827         if(prototypeMode){
00828                 if(newConnectionGroupMap.contains(conGrpID)){//Deleting a new connection group
00829                         newConnectionGroupMap.remove(conGrpID);
00830                 }
00831                 if(volatileConnectionGroupMap.contains(conGrpID)){//Don't update weights on this group any more
00832                         volatileConnectionGroupMap.remove(conGrpID);
00833                 }
00834                 else{//Schedule connection group for deletion when network is saved
00835                         deleteConnectionGroupIDs.append(conGrpID);
00836                 }
00837         }
00838 
00839         //Remove connection group from memory
00840         delete connGrpMap[conGrpID];
00841         connGrpMap.remove(conGrpID);
00842 }
00843 
00844 
00846 void Network::deleteNeuronGroupFromMemory(unsigned neurGrpID){
00847         //Remove neuron group from map of new groups that only exist in memory
00848         if(prototypeMode){
00849                 if(newNeuronGroupMap.contains(neurGrpID)){//Deleting a new neuron group
00850                         newNeuronGroupMap.remove(neurGrpID);
00851                 }
00852                 else{//Schedule neuron group for deletion when network is saved
00853                         deleteNeuronGroupIDs.append(neurGrpID);
00854                 }
00855         }
00856 
00857         //Identify connection groups involving this neuron group
00858         QHash<unsigned, bool> tmpDeleteConMap;
00859         for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter){
00860                 if(iter.value()->getFromNeuronGroupID() == neurGrpID || iter.value()->getToNeuronGroupID() == neurGrpID){
00861                         tmpDeleteConMap[iter.value()->getID()] = true;
00862                 }
00863         }
00864 
00865         //Remove neuron group from memory
00866         delete neurGrpMap[neurGrpID];
00867         neurGrpMap.remove(neurGrpID);
00868 
00869         //Delete connection groups from memory and schedule their later deletion from the database
00870         for(QHash<unsigned, bool>::iterator iter = tmpDeleteConMap.begin(); iter != tmpDeleteConMap.end(); ++iter)
00871                 deleteConnectionGroupFromMemory(iter.key());
00872 }
00873 
00874 
00877 bool Network::filterConnection(Connection *connection, unsigned connectionMode){
00878         //Filter by weight
00879         if(connectionMode & SHOW_POSITIVE_CONNECTIONS){
00880                 if(connection->getWeight() < 0 || connection->getTempWeight() < 0)
00881                         return true;
00882         }
00883         else if(connectionMode & SHOW_NEGATIVE_CONNECTIONS){
00884                 if(connection->getWeight() >= 0 || connection->getTempWeight() >= 0)
00885                         return true;
00886         }
00887         return false;
00888 }
00889 
00890 
00893 unsigned Network::getTemporaryConGrpID(){
00894         unsigned tmpID = 0xffffffff;
00895         while (connGrpMap.contains(tmpID)){
00896                 --tmpID;
00897                 if(tmpID == 0)
00898                         throw SpikeStreamException("Cannot find a temporary connection ID");
00899         }
00900         return tmpID;
00901 }
00902 
00903 
00906 unsigned Network::getTemporaryNeurGrpID(){
00907         unsigned tmpID = 0xffffffff;
00908         while (neurGrpMap.contains(tmpID)){
00909                 --tmpID;
00910                 if(tmpID == 0)
00911                         throw SpikeStreamException("Cannot find a temporary neuron group ID");
00912         }
00913         return tmpID;
00914 }
00915 
00916 
00918 void Network::initializeVariables(){
00919         transient = false;
00920         currentNeuronTask = -1;
00921         currentConnectionTask = -1;
00922         prototypeMode = false;
00923         clearError();
00924         neuronGroupParametersChanged = false;
00925         connectionGroupParametersChanged = false;
00926 }
00927 
00928 
00930 void Network::loadConnectionGroupsInfo(){
00931     //Clear hash map
00932         clearConnectionGroups();
00933 
00934     //Get list of neuron groups from database
00935         NetworkDao networkDao(networkDBInfo);
00936         QList<ConnectionGroupInfo> conGrpInfoList;
00937         networkDao.getConnectionGroupsInfo(getID(), conGrpInfoList);
00938 
00939     //Copy list into hash map for faster access
00940         for(int i=0; i<conGrpInfoList.size(); ++i)
00941                 connGrpMap[ conGrpInfoList[i].getID() ] = new ConnectionGroup(conGrpInfoList[i]);
00942 }
00943 
00944 
00947 void Network::loadNeuronGroupsInfo(){
00948     //Clear hash map
00949         clearNeuronGroups();
00950 
00951     //Get list of neuron groups from database
00952         NetworkDao networkDao(networkDBInfo);
00953         QList<NeuronGroupInfo> neurGrpInfoList;
00954         networkDao.getNeuronGroupsInfo(getID(), neurGrpInfoList);
00955 
00956     //Copy list into hash map for faster access
00957     for(int i=0; i<neurGrpInfoList.size(); ++i)
00958                 neurGrpMap[ neurGrpInfoList[i].getID() ] = new NeuronGroup(neurGrpInfoList[i]);
00959 }
00960 
00961 
00963 void Network::clearConnectionGroups(){
00964     for(QHash<unsigned int, ConnectionGroup*>::iterator iter = connGrpMap.begin(); iter != connGrpMap.end(); ++iter)
00965                 delete iter.value();
00966     connGrpMap.clear();
00967 }
00968 
00969 
00971 void Network::clearNeuronGroups(){
00972     //Delete all neuron groups
00973     for(QHash<unsigned int, NeuronGroup*>::iterator iter = neurGrpMap.begin(); iter != neurGrpMap.end(); ++iter)
00974                 delete iter.value();
00975     neurGrpMap.clear();
00976 }
00977 
00978 
00980 void Network::setError(const QString& errorMsg){
00981         this->errorMessage += " " + errorMsg;
00982         error = true;
00983 }
00984 
00985 
00987 void Network::startAddConnectionGroups(){
00988         clearError();
00989         QList<ConnectionGroup*> tmpConGrpList = newConnectionGroupMap.values();
00990         connectionNetworkDaoThread->prepareAddConnectionGroups(getID(), tmpConGrpList);
00991         currentConnectionTask = ADD_CONNECTIONS_TASK;
00992         connectionNetworkDaoThread->start();
00993 }
00994 
00995 
00997 void Network::startAddNeuronGroups(){
00998         clearError();
00999         QList<NeuronGroup*> tmpNeurGrpList = newNeuronGroupMap.values();
01000         neuronNetworkDaoThread->prepareAddNeuronGroups(getID(), tmpNeurGrpList);
01001         currentNeuronTask = ADD_NEURONS_TASK;
01002         neuronNetworkDaoThread->start();
01003 }
01004 
01005 
01007 void Network::startDeleteConnectionGroups(QList<unsigned>& deleteConGrpIDList){
01008         clearError();
01009         connectionNetworkDaoThread->prepareDeleteConnectionGroups(getID(), deleteConGrpIDList);
01010         currentConnectionTask = DELETE_CONNECTIONS_TASK;
01011         connectionNetworkDaoThread->start();
01012 }
01013 
01014 
01016 void Network::startDeleteNeuronGroups(QList<unsigned>& deleteNeurGrpIDList){
01017         clearError();
01018         neuronNetworkDaoThread->prepareDeleteNeuronGroups(getID(), deleteNeurGrpIDList);
01019         currentNeuronTask = DELETE_NEURONS_TASK;
01020         neuronNetworkDaoThread->start();
01021 }
01022 
01023 
01027 void Network::updateConnectionGroupsAfterSave(){
01028         //Add connection groups to network now that they have the correct ID or delete them if task has been cancelled
01029         for(QHash<unsigned, ConnectionGroup*>::iterator iter = newConnectionGroupMap.begin(); iter != newConnectionGroupMap.end(); ++iter){
01030                 if(connGrpMap.contains(iter.value()->getID()))
01031                         throw SpikeStreamException("Connection group with ID " + QString::number(iter.value()->getID()) + " is already present in the network.");
01032                 if(connectionTaskCancelled)
01033                         delete iter.value();
01034                 else
01035                         connGrpMap[iter.value()->getID()] = iter.value();
01036         }
01037         newConnectionGroupMap.clear();
01038 }
01039 
01040 
01044 void Network::updateNeuronGroupsAfterSave(){
01045         //Add neuron groups to the network now that they have the correct ID, or delete if task has not been cancelled
01046         for(QHash<unsigned, NeuronGroup*>::iterator iter = newNeuronGroupMap.begin(); iter != newNeuronGroupMap.end(); ++iter){
01047                 //Check to see if ID already exists - error in this case
01048                 if( neurGrpMap.contains( iter.value()->getID() ) ){
01049                         throw SpikeStreamException("Adding neurons task - trying to add a neuron group with ID " + QString::number(iter.value()->getID()) + " that already exists in the network.");
01050                 }
01051                 if(neuronTaskCancelled)
01052                         delete iter.value();
01053                 else
01054                         neurGrpMap[ iter.value()->getID() ] = iter.value();
01055         }
01056         newNeuronGroupMap.clear();
01057 }
01058 
01059 
 All Classes Files Functions Variables Typedefs Defines