SpikeStream Library
0.2
|
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