SpikeStream Nemo Plugin
0.2
|
00001 //SpikeStream includes 00002 #include "Globals.h" 00003 #include "NemoLoader.h" 00004 #include "NemoWrapper.h" 00005 #include "PerformanceTimer.h" 00006 #include "SpikeStreamException.h" 00007 #include "SpikeStreamSimulationException.h" 00008 #include "STDPFunctions.h" 00009 #include "Util.h" 00010 using namespace spikestream; 00011 00012 //Other includes 00013 #include "boost/random.hpp" 00014 00015 //Outputs debugging information for NeMo calls 00016 //#define DEBUG_INJECT_CURRENT 00017 //#define DEBUG_INJECT_NOISE 00018 //#define DEBUG_LEARNING 00019 //#define DEBUG_LOAD 00020 //#define DEBUG_PARAMETERS 00021 //#define DEBUG_PERFORMANCE 00022 //#define DEBUG_STEP 00023 //#define DEBUG_WEIGHTS 00024 //#define TIME_PERFORMANCE 00025 00026 #ifdef TIME_PERFORMANCE 00027 unsigned numberOfFiringNeurons = 0; 00028 #endif//TIME_PERFORMANCE 00029 00030 00032 NemoWrapper::NemoWrapper() : AbstractSimulation() { 00033 //Initialise variables 00034 currentTaskID = NO_TASK_DEFINED; 00035 simulationLoaded = false; 00036 stopThread = true; 00037 archiveMode = false; 00038 monitorFiringNeurons = false; 00039 updateFiringNeurons = false; 00040 monitorMembranePotential = false; 00041 monitor = true; 00042 monitorWeights = false; 00043 updateInterval_ms = 500; 00044 patternNeuronGroupID = 0; 00045 sustainPattern = false; 00046 sustainCurrent = false; 00047 waitInterval_ms = 200; 00048 00049 //Zero is the default STDP function 00050 stdpFunctionID = 0; 00051 00052 //Get a nemo configuration object initialized with the default values 00053 nemoConfig = nemo_new_configuration(); 00054 } 00055 00056 00058 NemoWrapper::~NemoWrapper(){ 00059 if(simulationLoaded) 00060 unloadSimulation(); 00061 } 00062 00063 00064 /*----------------------------------------------------------*/ 00065 /*----- PUBLIC METHODS -----*/ 00066 /*----------------------------------------------------------*/ 00067 00069 void NemoWrapper::addDeviceManager(AbstractDeviceManager* deviceManager){ 00070 deviceManagerList.append(deviceManager); 00071 } 00072 00073 00075 void NemoWrapper::cancelLoading(){ 00076 stopThread = true; 00077 } 00078 00079 00081 void NemoWrapper::cancelResetWeights(){ 00082 weightResetCancelled = true; 00083 } 00084 00085 00087 void NemoWrapper::cancelSaveWeights(){ 00088 weightSaveCancelled = true; 00089 } 00090 00091 00093 bool NemoWrapper::isSimulationRunning(){ 00094 if(currentTaskID == RUN_SIMULATION_TASK || currentTaskID == STEP_SIMULATION_TASK) 00095 return true; 00096 return false; 00097 } 00098 00099 00103 void NemoWrapper::loadNemo(){ 00104 simulationLoaded = false; 00105 nemoSimulation = NULL; 00106 timeStepCounter = 0; 00107 waitForGraphics = false; 00108 archiveMode = false; 00109 00110 // Set the NeMo plugin path 00111 QString pluginPath = Globals::getSpikeStreamRoot()+"/bin/nemo-plugins"; 00112 qDebug()<<"Nemo plugin path: "<<pluginPath; 00113 checkNemoOutput( 00114 nemo_add_plugin_path(pluginPath.toAscii()), 00115 "NeMo error setting plugin path." 00116 ); 00117 00118 //Get the network 00119 if(!Globals::networkLoaded()) 00120 throw SpikeStreamSimulationException("Cannot load simulation: no network loaded."); 00121 Network* currentNetwork = Globals::getNetwork(); 00122 00123 //Set up the archive info 00124 archiveInfo.reset(); 00125 archiveInfo.setNetworkID(currentNetwork->getID()); 00126 00127 //Build the Nemo network 00128 NemoLoader* nemoLoader = new NemoLoader(); 00129 connect(nemoLoader, SIGNAL(progress(int, int)), this, SLOT(updateProgress(int, int))); 00130 #ifdef DEBUG_LOAD 00131 qDebug()<<"About to build nemo network."; 00132 #endif//DEBUG_LOAD 00133 nemo_network_t nemoNet = nemoLoader->buildNemoNetwork(currentNetwork, volatileConGrpMap, &stopThread); 00134 #ifdef DEBUG_LOAD 00135 qDebug()<<"Nemo network successfully built."; 00136 #endif//DEBUG_LOAD 00137 00138 //Clean up loader 00139 delete nemoLoader; 00140 00141 //Set the STDP functionn in the configuration 00142 #ifdef DEBUG_LEARNING 00143 STDPFunctions::print(stdpFunctionID); 00144 #endif 00145 checkNemoOutput( 00146 nemo_set_stdp_function(nemoConfig, 00147 STDPFunctions::getPreArray(stdpFunctionID), 00148 STDPFunctions::getPreLength(stdpFunctionID), 00149 STDPFunctions::getPostArray(stdpFunctionID), 00150 STDPFunctions::getPostLength(stdpFunctionID), 00151 STDPFunctions::getMinExcitatoryWeight(stdpFunctionID), 00152 STDPFunctions::getMaxExcitatoryWeight(stdpFunctionID), 00153 STDPFunctions::getMinInhibitoryWeight(stdpFunctionID), 00154 STDPFunctions::getMaxInhibitoryWeight(stdpFunctionID) 00155 ), 00156 "Nemo error setting STDP function." 00157 ); 00158 00159 stdpReward = STDPFunctions::getReward(stdpFunctionID); 00160 applySTDPInterval = STDPFunctions::getApplySTDPInterval(stdpFunctionID); 00161 00162 //Load the network into the simulator 00163 #ifdef DEBUG_LOAD 00164 qDebug()<<"About to load nemo network into simulator."; 00165 #endif//DEBUG_LOAD 00166 nemoSimulation = nemo_new_simulation(nemoNet, nemoConfig); 00167 if(nemoSimulation == NULL) { 00168 throw SpikeStreamSimulationException(QString("Failed to create Nemo simulation: ") + nemo_strerror()); 00169 } 00170 #ifdef DEBUG_LOAD 00171 qDebug()<<"Nemo network successfully loaded into simulator."; 00172 #endif//DEBUG_LOAD 00173 00174 if(!stopThread) 00175 simulationLoaded = true; 00176 } 00177 00178 00180 void NemoWrapper::playSimulation(){ 00181 if(!simulationLoaded) 00182 throw SpikeStreamException("Cannot run simulation - no simulation loaded."); 00183 00184 //Do nothing if we are already in play mode 00185 if(currentTaskID == RUN_SIMULATION_TASK) 00186 return; 00187 00188 runMutex.lock(); 00189 currentTaskID = RUN_SIMULATION_TASK; 00190 runMutex.unlock(); 00191 00192 } 00193 00194 00196 void NemoWrapper::resetWeights(){ 00197 if(!simulationLoaded) 00198 throw SpikeStreamException("Cannot reset weights - no simulation loaded."); 00199 weightsReset = false; 00200 weightResetCancelled = false; 00201 currentTaskID = RESET_WEIGHTS_TASK; 00202 } 00203 00204 00206 void NemoWrapper::saveWeights(){ 00207 if(!simulationLoaded) 00208 throw SpikeStreamException("Cannot save weights - no simulation loaded."); 00209 weightsSaved = false; 00210 weightSaveCancelled = false; 00211 currentTaskID = SAVE_WEIGHTS_TASK; 00212 } 00213 00217 void NemoWrapper::setInjectCurrent(unsigned neuronGroupID, double percentage, double current, bool sustain){ 00218 sustainCurrent = sustain; 00219 sustainNoise = sustain;//Both are controlled with a single check box 00220 00221 //Run checks 00222 if(!simulationLoaded) 00223 throw SpikeStreamException("Current cannot be injected when a simulation is not loaded."); 00224 if(percentage < 0.0 || percentage > 100.0) 00225 throw SpikeStreamException("Injecting current. Percentage is out of range"); 00226 if(!Globals::getNetwork()->containsNeuronGroup(neuronGroupID)) 00227 throw SpikeStreamException("Injecting current. Neuron group ID cannot be found in current network: " + QString::number(neuronGroupID)); 00228 00229 //Calculate number of neurons to fire and store it in the map 00230 unsigned numNeuronsToFire = Util::rUInt( (percentage / 100.0) * (double)Globals::getNetwork()->getNeuronGroup(neuronGroupID)->size()); 00231 if(numNeuronsToFire > (unsigned)Globals::getNetwork()->getNeuronGroup(neuronGroupID)->size()) 00232 throw SpikeStreamException("Number of neurons to fire is greater than neuron group size: " + QString::number(numNeuronsToFire) ); 00233 00234 injectCurrentMap[neuronGroupID] = QPair<unsigned, double>(numNeuronsToFire, current); 00235 } 00236 00237 00239 void NemoWrapper::setFiringNeuronIDs(QList<neurid_t>& neurIDList){ 00240 //Run checks 00241 if(!simulationLoaded) 00242 throw SpikeStreamException("Neurons cannot be fired when a simulation is not loaded."); 00243 00244 //Pointer to current network 00245 Network* nwPtr = Globals::getNetwork(); 00246 00247 QList<neurid_t>::iterator neurIDListEnd = neurIDList.end(); 00248 for(QList<neurid_t>::iterator iter = neurIDList.begin(); iter != neurIDListEnd; ++iter){ 00249 if(!nwPtr->containsNeuron(*iter)) 00250 throw SpikeStreamException("Neuron ID " + QString::number(*iter) + " cannot be found in the network."); 00251 neuronIDsToFire.append(*iter); 00252 } 00253 } 00254 00255 00257 void NemoWrapper::setInjectCurrentNeuronIDs(QList<neurid_t>& neurIDList, double current){ 00258 //Run checks 00259 if(!simulationLoaded) 00260 throw SpikeStreamException("Neurons cannot be injected with current when a simulation is not loaded."); 00261 00262 //Pointer to current network 00263 Network* nwPtr = Globals::getNetwork(); 00264 00265 QList<neurid_t>::iterator neurIDListEnd = neurIDList.end(); 00266 for(QList<neurid_t>::iterator iter = neurIDList.begin(); iter != neurIDListEnd; ++iter){ 00267 if(!nwPtr->containsNeuron(*iter)) 00268 throw SpikeStreamException("Neuron ID " + QString::number(*iter) + " cannot be found in the network."); 00269 neuronIDCurrentMap[*iter] = current; 00270 } 00271 } 00272 00273 00277 void NemoWrapper::setInjectNoise(unsigned neuronGroupID, double percentage, bool sustain){ 00278 sustainNoise = sustain; 00279 sustainCurrent = sustain;//Both are controlled with a single check box 00280 00281 //Run checks 00282 if(!simulationLoaded) 00283 throw SpikeStreamException("Noise cannot be injected when a simulation is not loaded."); 00284 if(percentage < 0.0 || percentage > 100.0) 00285 throw SpikeStreamException("Injecting noise. Percentage is out of range"); 00286 if(!Globals::getNetwork()->containsNeuronGroup(neuronGroupID)) 00287 throw SpikeStreamException("Injecting noise. Neuron group ID cannot be found in current network: " + QString::number(neuronGroupID)); 00288 00289 //Calculate number of neurons to fire and store it in the map 00290 injectNoiseMap[neuronGroupID] = Util::rUInt( (percentage / 100.0) * (double)Globals::getNetwork()->getNeuronGroup(neuronGroupID)->size()); 00291 if(injectNoiseMap[neuronGroupID] > (unsigned)Globals::getNetwork()->getNeuronGroup(neuronGroupID)->size()) 00292 throw SpikeStreamException("Number of neurons to fire is greater than neuron group size: " + QString::number(injectNoiseMap[neuronGroupID])); 00293 } 00294 00295 00297 void NemoWrapper::stepSimulation(){ 00298 if(!simulationLoaded) 00299 throw SpikeStreamException("Cannot step simulation - no simulation loaded."); 00300 00301 //Do nothing if we are already in step mode 00302 if(currentTaskID == STEP_SIMULATION_TASK) 00303 return; 00304 00305 //Lock mutex to prevent interference with current task 00306 runMutex.lock(); 00307 00308 //Set to step mode for when run loop is next ready 00309 currentTaskID = STEP_SIMULATION_TASK; 00310 00311 //Release mutex 00312 runMutex.unlock(); 00313 } 00314 00315 00316 // Run method inherited from QThread 00317 void NemoWrapper::run(){ 00318 stopThread = false; 00319 clearError(); 00320 00321 try{ 00322 //Create thread specific network and archive daos 00323 networkDao = new NetworkDao(Globals::getNetworkDao()->getDBInfo()); 00324 archiveDao = new ArchiveDao(Globals::getArchiveDao()->getDBInfo()); 00325 00326 //Load up the simulation and reset the task ID 00327 loadNemo(); 00328 currentTaskID = NO_TASK_DEFINED; 00329 00330 //Wait for run or step command 00331 while(!stopThread){ 00332 runMutex.lock(); 00333 00334 //Run simulation 00335 if(currentTaskID == RUN_SIMULATION_TASK){ 00336 runNemo(); 00337 } 00338 //Step simulation 00339 else if(currentTaskID == STEP_SIMULATION_TASK){ 00340 stepNemo(); 00341 } 00342 //Reset weights 00343 else if(currentTaskID == RESET_WEIGHTS_TASK){ 00344 resetNemoWeights(); 00345 } 00346 //Save weights 00347 else if(currentTaskID == SAVE_WEIGHTS_TASK){ 00348 saveNemoWeights(); 00349 } 00350 //Set neuron parameters 00351 else if(currentTaskID == SET_NEURON_PARAMETERS_TASK){ 00352 setNeuronParametersInNemo(); 00353 } 00354 //Do nothing 00355 else if(currentTaskID == NO_TASK_DEFINED){ 00356 ;//Do nothing 00357 } 00358 //Task ID not recognized 00359 else{ 00360 throw SpikeStreamException("Task ID not recognizedL: " + QString::number(currentTaskID)); 00361 } 00362 00363 //Reset task ID 00364 currentTaskID = NO_TASK_DEFINED;//Don't want it to continue stepping. 00365 00366 runMutex.unlock(); 00367 00368 //Short sleep waiting for the next command 00369 msleep(waitInterval_ms); 00370 } 00371 00372 //Clean up the thread specific network and archive daos 00373 delete networkDao; 00374 delete archiveDao; 00375 } 00376 catch(SpikeStreamException& ex){ 00377 setError(ex.getMessage()); 00378 } 00379 catch(...){ 00380 setError("An unknown error occurred while NemoWrapper thread was running."); 00381 } 00382 00383 unloadNemo(); 00384 00385 stopThread = true; 00386 } 00387 00388 00392 void NemoWrapper::setFrameRate(unsigned int frameRate){ 00393 QMutexLocker locker(&mutex); 00394 if(frameRate == 0) 00395 this->updateInterval_ms = 0; 00396 else 00397 this->updateInterval_ms = 1000 / frameRate; 00398 } 00399 00400 00403 void NemoWrapper::setArchiveMode(bool newArchiveMode, const QString& description){ 00404 if(newArchiveMode && !simulationLoaded) 00405 throw SpikeStreamSimulationException("Cannot switch archive mode on unless simulation is loaded."); 00406 00407 /* Create archive if this is the first time the mode has been set 00408 Use globals archive dao because this method is called from a separate thread */ 00409 if(archiveInfo.getID() == 0){ 00410 archiveInfo.setDescription(description); 00411 Globals::getArchiveDao()->addArchive(archiveInfo); 00412 Globals::getEventRouter()->archiveListChangedSlot(); 00413 } 00414 //Rename archive if one is already loaded 00415 else{ 00416 archiveInfo.setDescription(description); 00417 Globals::getArchiveDao()->setArchiveProperties(archiveInfo.getID(), description); 00418 Globals::getEventRouter()->archiveListChangedSlot(); 00419 } 00420 00421 this->archiveMode = newArchiveMode; 00422 } 00423 00424 00427 void NemoWrapper::setFiringInjectionPattern(const Pattern& pattern, unsigned neuronGroupID, bool sustain){ 00428 //Lock mutex to prevent multiple threads accessing injection vector 00429 mutex.lock(); 00430 00431 sustainPattern = sustain; 00432 00433 //Get copy of the pattern that is aligned on the centre of the neuron group 00434 NeuronGroup* neurGrp = Globals::getNetwork()->getNeuronGroup(neuronGroupID); 00435 Pattern alignedPattern( pattern.getAlignedPattern(neurGrp->getBoundingBox()) ); 00436 00437 //Add neurons that are contained within the pattern 00438 NeuronMap::iterator neuronMapEnd = neurGrp->end(); 00439 for(NeuronMap::iterator iter = neurGrp->begin(); iter != neuronMapEnd; ++iter){ 00440 if(alignedPattern.contains( (*iter)->getLocation() ) ){ 00441 injectionPatternVector.push_back( (*iter)->getID()); 00442 } 00443 } 00444 //Release mutex 00445 mutex.unlock(); 00446 } 00447 00448 00451 void NemoWrapper::setCurrentInjectionPattern(const Pattern& pattern, float current, unsigned neuronGroupID, bool sustain){ 00452 //Lock mutex to prevent multiple threads accessing current vectors 00453 mutex.lock(); 00454 00455 sustainPattern = sustain; 00456 00457 //Get copy of the pattern that is aligned on the centre of the neuron group 00458 NeuronGroup* neurGrp = Globals::getNetwork()->getNeuronGroup(neuronGroupID); 00459 Pattern alignedPattern( pattern.getAlignedPattern(neurGrp->getBoundingBox()) ); 00460 00461 //Add neurons that are contained within the pattern 00462 NeuronMap::iterator neuronMapEnd = neurGrp->end(); 00463 for(NeuronMap::iterator iter = neurGrp->begin(); iter != neuronMapEnd; ++iter){ 00464 if(alignedPattern.contains( (*iter)->getLocation() ) ){ 00465 injectionCurrentNeurIDVector.push_back( (*iter)->getID()); 00466 injectionCurrentVector.push_back(current); 00467 } 00468 } 00469 00470 mutex.unlock(); 00471 } 00472 00473 00476 void NemoWrapper::setMonitorNeurons(bool firing, bool membranePotential){ 00477 if( (firing || membranePotential) && !simulationLoaded) 00478 throw SpikeStreamSimulationException("Cannot switch neuron monitor mode on unless simulation is loaded."); 00479 if(firing && membranePotential) 00480 throw SpikeStreamSimulationException("Cannot monitor firing neurons and membrane potential at the same time."); 00481 00482 //Store new monitoring mode 00483 this->monitorFiringNeurons = firing; 00484 this->monitorMembranePotential = membranePotential; 00485 } 00486 00487 00489 void NemoWrapper::setMonitor(bool mode){ 00490 this->monitor = mode; 00491 } 00492 00493 00496 void NemoWrapper::setMonitorWeights(bool enable){ 00497 monitorWeights = enable; 00498 } 00499 00500 00502 void NemoWrapper::setNeuronParameters(unsigned neuronGroupID, QHash<QString, double> parameterMap){ 00503 if(!simulationLoaded) 00504 throw SpikeStreamException("Cannot set neuron parameters - no simulation loaded."); 00505 this->neuronGroupID = neuronGroupID; 00506 neuronParameterMap = parameterMap; 00507 currentTaskID = SET_NEURON_PARAMETERS_TASK; 00508 } 00509 00510 00512 void NemoWrapper::setSynapseParameters(unsigned, QHash<QString, double>){ 00513 if(!simulationLoaded) 00514 throw SpikeStreamException("Cannot set synapse parameters - no simulation loaded."); 00515 throw SpikeStreamException("This method should not be called because it is not implemented."); 00516 } 00517 00518 00520 void NemoWrapper::stopSimulation(){ 00521 currentTaskID = NO_TASK_DEFINED; 00522 } 00523 00524 00526 void NemoWrapper::unloadSimulation(){ 00527 stopThread = true; 00528 } 00529 00530 00531 00532 /*----------------------------------------------------------*/ 00533 /*----- PRIVATE SLOTS -----*/ 00534 /*----------------------------------------------------------*/ 00535 00538 void NemoWrapper::updateProgress(int stepsComplete, int totalSteps){ 00539 emit progress(stepsComplete, totalSteps); 00540 } 00541 00542 00543 /*----------------------------------------------------------*/ 00544 /*----- PRIVATE METHODS -----*/ 00545 /*----------------------------------------------------------*/ 00546 00550 unsigned NemoWrapper::addInjectFiringNeuronIDs(){ 00551 //Calculate total number of firing neurons 00552 unsigned arraySize = 0, arrayCounter = 0; 00553 for(QHash<unsigned, unsigned>::iterator iter = injectNoiseMap.begin(); iter != injectNoiseMap.end(); ++iter) 00554 arraySize += iter.value(); 00555 00556 //Add a random selection of neuron ids from each group 00557 unsigned randomIndex, neurGrpSize, numSelectedNeurons; 00558 QHash<unsigned, bool> addedNeurIndxMap;//Prevent duplicates 00559 for(QHash<unsigned, unsigned>::iterator iter = injectNoiseMap.begin(); iter != injectNoiseMap.end(); ++iter){ 00560 //Get list of neuron ids 00561 QList<unsigned> neuronIDList = Globals::getNetwork()->getNeuronGroup(iter.key())->getNeuronIDs(); 00562 neurGrpSize = neuronIDList.size(); 00563 addedNeurIndxMap.clear(); 00564 numSelectedNeurons = iter.value(); 00565 #ifdef DEBUG_INJECT_NOISE 00566 qDebug()<<"Selecting random neurons for injecting noise. Num neurons: "<<neurGrpSize<<"; num neurons to select: "<<numSelectedNeurons; 00567 #endif//DEBUG_INJECT_NOISE 00568 00569 //Select indexes from the list of neuron ids 00570 while((unsigned)addedNeurIndxMap.size() < numSelectedNeurons){ 00571 randomIndex = Util::getRandom(0, neurGrpSize);//Get random position in list of neuron ids 00572 if(!addedNeurIndxMap.contains(randomIndex)){//New index 00573 if(arrayCounter >= arraySize)//Sanity check 00574 throw SpikeStreamException("Error adding noise injection neuron ids - array counter out of range."); 00575 injectionPatternVector.push_back(neuronIDList.at(randomIndex));//Add neuron id to pattern vector 00576 #ifdef DEBUG_INJECT_NOISE 00577 qDebug()<<"Random index: "<<randomIndex<<"; Inject noise neuron ID: "<<neuronIDList.at(randomIndex); 00578 #endif//DEBUG_INJECT_NOISE 00579 addedNeurIndxMap[randomIndex] = true;//Record the fact that we have selected this ID 00580 ++arrayCounter; 00581 } 00582 } 00583 } 00584 00585 //Sanity check, then return number of neurons added 00586 if(arrayCounter != arraySize) 00587 throw SpikeStreamException("Error adding inject noise neuron IDs. Array counter: " + QString::number(arrayCounter) + "; Array size: " + QString::number(arraySize)); 00588 00589 //Add neurons that are specified to fire during this time step 00590 QList<neurid_t>::iterator neurIDListFireEnd = neuronIDsToFire.end(); 00591 for(QList<neurid_t>::iterator iter = neuronIDsToFire.begin(); iter != neurIDListFireEnd; ++iter){ 00592 injectionPatternVector.push_back(*iter); 00593 ++arraySize; 00594 } 00595 neuronIDsToFire.clear(); 00596 00597 //Add firing neuron IDs from plugins 00598 for(int i=0; i<deviceManagerList.size(); ++i){ 00599 if(deviceManagerList[i]->isFireNeuronMode()){//Only add firing neuron IDs if we are in firing neuron mode 00600 QList<neurid_t>::iterator outputNeuronsEnd = deviceManagerList[i]->outputNeuronsEnd(); 00601 for(QList<neurid_t>::iterator iter = deviceManagerList[i]->outputNeuronsBegin(); iter != outputNeuronsEnd; ++iter){ 00602 injectionPatternVector.push_back(*iter); 00603 ++arraySize; 00604 } 00605 } 00606 } 00607 00608 //Return the number of neurons that have been added 00609 return arraySize; 00610 } 00611 00612 00614 unsigned NemoWrapper::addInjectCurrentNeuronIDs(){ 00615 //Calculate total number of current neurons 00616 unsigned arraySize = 0, arrayCounter = 0; 00617 for(QHash<unsigned, QPair<unsigned, double> >::iterator iter = injectCurrentMap.begin(); iter != injectCurrentMap.end(); ++iter) 00618 arraySize += iter.value().first; 00619 00620 //Add a random selection of neuron ids from each group 00621 unsigned randomIndex, neurGrpSize, numSelectedNeurons; 00622 double injectCurrentAmount; 00623 QHash<unsigned, bool> addedNeurIndxMap;//Prevent duplicates 00624 for(QHash<unsigned, QPair<unsigned, double> >::iterator iter = injectCurrentMap.begin(); iter != injectCurrentMap.end(); ++iter){ 00625 //Get list of neuron ids 00626 QList<unsigned> neuronIDList = Globals::getNetwork()->getNeuronGroup(iter.key())->getNeuronIDs(); 00627 neurGrpSize = neuronIDList.size(); 00628 addedNeurIndxMap.clear(); 00629 numSelectedNeurons = iter.value().first; 00630 injectCurrentAmount = iter.value().second; 00631 00632 //Select indexes from the list of neuron ids 00633 while((unsigned)addedNeurIndxMap.size() < numSelectedNeurons){ 00634 randomIndex = Util::getRandom(0, neurGrpSize);//Get random position in list of neuron ids 00635 if(!addedNeurIndxMap.contains(randomIndex)){//New index 00636 if(arrayCounter >= arraySize)//Sanity check 00637 throw SpikeStreamException("Error adding current injection neuron ids - array counter out of range."); 00638 injectionCurrentNeurIDVector.push_back(neuronIDList.at(randomIndex));//Add neuron id to pattern vector 00639 injectionCurrentVector.push_back(injectCurrentAmount); 00640 addedNeurIndxMap[randomIndex] = true;//Record the fact that we have selected this ID 00641 ++arrayCounter; 00642 } 00643 } 00644 } 00645 00646 //Sanity check, then return number of neurons added 00647 if(arrayCounter != arraySize) 00648 throw SpikeStreamException("Error adding inject noise neuron IDs. Array counter: " + QString::number(arrayCounter) + "; Array size: " + QString::number(arraySize)); 00649 00650 //Add neurons that have specified amount of current 00651 QHash<neurid_t, double>::iterator neurIDCurrentMapEnd = neuronIDCurrentMap.end(); 00652 for(QHash<neurid_t, double>::iterator iter = neuronIDCurrentMap.begin(); iter != neurIDCurrentMapEnd; ++iter){ 00653 injectionCurrentNeurIDVector.push_back(iter.key());//Add neuron id to current vector 00654 injectionCurrentVector.push_back(iter.value()); 00655 #ifdef DEBUG_INJECT_CURRENT 00656 qDebug()<<"TimeStep: "<<timeStepCounter<<". Injecting "<<iter.value()<<" current into neuron "<<iter.key(); 00657 #endif//DEBUG_INJECT_CURRENT 00658 ++arraySize; 00659 } 00660 neuronIDCurrentMap.clear(); 00661 00662 //Add inject current neuron IDs from plugins 00663 for(int i=0; i<deviceManagerList.size(); ++i){ 00664 if(!deviceManagerList[i]->isFireNeuronMode()){//Only add inject current neuron ids if firing neuron mode is off 00665 QList<neurid_t>::iterator outputNeuronsEnd = deviceManagerList[i]->outputNeuronsEnd(); 00666 double tmpCurrent = deviceManagerList[i]->getCurrent(); 00667 for(QList<neurid_t>::iterator iter = deviceManagerList[i]->outputNeuronsBegin(); iter != outputNeuronsEnd; ++iter){ 00668 injectionCurrentNeurIDVector.push_back(*iter);//Add neuron id to current vector 00669 injectionCurrentVector.push_back(tmpCurrent); 00670 ++arraySize; 00671 } 00672 } 00673 } 00674 00675 //Return the number of neurons that have been added 00676 return arraySize; 00677 } 00678 00679 00681 void NemoWrapper::checkNemoOutput(nemo_status_t result, const QString& errorMessage){ 00682 if(result != NEMO_OK) 00683 throw SpikeStreamException(errorMessage + ": " + nemo_strerror()); 00684 } 00685 00686 00688 void NemoWrapper::clearError(){ 00689 error = false; 00690 errorMessage = ""; 00691 } 00692 00693 00695 void NemoWrapper::fillInjectNoiseArray(unsigned*& array, int* arraySize){ 00696 //Calculate total number of firing neurons 00697 *arraySize = 0; 00698 for(QHash<unsigned, unsigned>::iterator iter = injectNoiseMap.begin(); iter != injectNoiseMap.end(); ++iter) 00699 *arraySize = *arraySize + iter.value(); 00700 00701 //Create array 00702 int arrayCounter = 0; 00703 array = new unsigned[*arraySize]; 00704 00705 //Fill array with a random selection of neuron ids from each group 00706 unsigned randomIndex, neurGrpSize, numSelectedNeurons; 00707 QHash<unsigned, bool> addedNeurIndxMap;//Prevent duplicates 00708 for(QHash<unsigned, unsigned>::iterator iter = injectNoiseMap.begin(); iter != injectNoiseMap.end(); ++iter){ 00709 //Get list of neuron ids 00710 QList<unsigned> neuronIDList = Globals::getNetwork()->getNeuronGroup(iter.key())->getNeuronIDs(); 00711 neurGrpSize = neuronIDList.size(); 00712 addedNeurIndxMap.clear(); 00713 numSelectedNeurons = iter.value(); 00714 00715 //Select indexes from the list of neuron ids 00716 while((unsigned)addedNeurIndxMap.size() < numSelectedNeurons){ 00717 randomIndex = Util::getRandom(0, neurGrpSize);//Get random position in list of neuron ids 00718 if(!addedNeurIndxMap.contains(randomIndex)){//New index 00719 if(arrayCounter >= *arraySize)//Sanity check 00720 throw SpikeStreamException("Error adding noise injection neuron ids - array counter out of range."); 00721 array[arrayCounter] = neuronIDList.at(randomIndex);//Add neuron id to array 00722 addedNeurIndxMap[randomIndex] = true;//Record the fact that we have selected this ID 00723 ++arrayCounter; 00724 } 00725 } 00726 } 00727 } 00728 00729 00731 void NemoWrapper::getMembranePotential(){ 00732 membranePotentialMap.clear(); 00733 00734 float tmpMemPot, maxMemPot = 0.0f, minMemPot = 0.0f; 00735 QList<NeuronGroup*> neurGrpList = Globals::getNetwork()->getNeuronGroups(); 00736 for(int i=0; i<neurGrpList.size(); ++i){ 00737 NeuronMap::iterator neurGrpListEnd = neurGrpList.at(i)->end(); 00738 for(NeuronMap::iterator iter = neurGrpList.at(i)->begin(); iter != neurGrpListEnd; ++iter){ 00739 checkNemoOutput(nemo_get_membrane_potential(nemoSimulation, iter.key(), &tmpMemPot), "Error getting membrane potential."); 00740 membranePotentialMap[iter.key()] = tmpMemPot; 00741 if(tmpMemPot > maxMemPot) 00742 maxMemPot = tmpMemPot; 00743 if(tmpMemPot < minMemPot) 00744 minMemPot = tmpMemPot; 00745 } 00746 } 00747 } 00748 00749 00751 void NemoWrapper::runNemo(){ 00752 //Check simulation is loaded 00753 if(!simulationLoaded) 00754 throw SpikeStreamSimulationException("Cannot run simulation - no simulation loaded."); 00755 00756 //Declare variables to use in the loop 00757 QTime startTime; 00758 unsigned int elapsedTime_ms; 00759 #ifdef TIME_PERFORMANCE 00760 unsigned timeTotal = 0; 00761 unsigned timeCounter = 0; 00762 numberOfFiringNeurons = 0; 00763 #endif//TIME_PERFORMANCE 00764 00765 while(currentTaskID == RUN_SIMULATION_TASK && !stopThread){ 00766 //Record the current time 00767 startTime = QTime::currentTime(); 00768 00769 //Lock mutex so that update time interval cannot change during this calculation 00770 mutex.lock(); 00771 00772 //Advance simulation one step 00773 stepNemo(); 00774 00775 //Sleep if task was completed in less than the prescribed interval 00776 if(updateInterval_ms > 0){ 00777 elapsedTime_ms = startTime.msecsTo(QTime::currentTime()); 00778 #ifdef DEBUG_PERFORMANCE 00779 qDebug()<<"Elapsed time: "<<elapsedTime_ms<<"; update interval: "<<updateInterval_ms; 00780 #endif//DEBUG_PERFORMANCE 00781 if(elapsedTime_ms < updateInterval_ms){ 00782 //Sleep for remaning time 00783 usleep(1000 * (updateInterval_ms - elapsedTime_ms)); 00784 } 00785 } 00786 00787 //Unlock mutex 00788 mutex.unlock(); 00789 00790 //Wait for graphics to update if we are monitoring the simulation 00791 while(!stopThread && waitForGraphics) 00792 usleep(1000); 00793 00794 #ifdef TIME_PERFORMANCE 00795 timeTotal += startTime.msecsTo(QTime::currentTime()); 00796 ++timeCounter; 00797 if(timeCounter > 1000) 00798 currentTaskID = NO_TASK_DEFINED; 00799 #endif//TIME_PERFORMANCE 00800 } 00801 00802 //Output performance measure 00803 #ifdef TIME_PERFORMANCE 00804 cout<<"Average time per timestep:"<<( (double)timeTotal / (double)timeCounter )<<" ms; Average number of firing neurons per ms: "<<( (double)numberOfFiringNeurons / (double)timeCounter )<<endl; 00805 #endif//TIME_PERFORMANCE 00806 00807 //Inform other classes that simulation has stopped playing 00808 emit simulationStopped(); 00809 } 00810 00811 00813 void NemoWrapper::resetNemoWeights(){ 00814 //Return immediately if there is nothing to save 00815 if(volatileConGrpMap.size() == 0){ 00816 weightsReset = true; 00817 weightsSaved = true; 00818 return; 00819 } 00820 00821 //Work through all connection groups 00822 Network* currentNetwork = Globals::getNetwork(); 00823 for(QHash<unsigned, synapse_id*>::iterator conGrpIter = volatileConGrpMap.begin(); conGrpIter != volatileConGrpMap.end(); ++conGrpIter){ 00824 ConnectionGroup* tmpConGrp = currentNetwork->getConnectionGroup(conGrpIter.key()); 00825 ConnectionIterator endConGrp = tmpConGrp->end(); 00826 for(ConnectionIterator conIter = tmpConGrp->begin(); conIter != endConGrp; ++conIter){ 00827 //Copy current weights to temporary weights 00828 conIter->setTempWeight(conIter->getWeight()); 00829 00830 //Check for cancellation 00831 if(weightResetCancelled){ 00832 Globals::getEventRouter()->weightsChangedSlot(); 00833 return; 00834 } 00835 } 00836 } 00837 00838 //Inform other classes about weight change 00839 Globals::getEventRouter()->weightsChangedSlot(); 00840 00841 //Weight are saved and reset 00842 weightsReset = true; 00843 weightsSaved = true; 00844 } 00845 00846 00848 void NemoWrapper::saveNemoWeights(){ 00849 //Return immediately if there is nothing to save 00850 if(volatileConGrpMap.size() == 0){ 00851 weightsSaved = true; 00852 return; 00853 } 00854 00855 //Update temporary weights in network to match weights in NeMo 00856 updateNetworkWeights(); 00857 00858 //Copy temporary weight to weight field in network 00859 Network* currentNetwork = Globals::getNetwork(); 00860 unsigned cntr = 0; 00861 for(QHash<unsigned, synapse_id*>::iterator conGrpIter = volatileConGrpMap.begin(); !weightSaveCancelled && conGrpIter != volatileConGrpMap.end(); ++conGrpIter){ 00862 currentNetwork->copyTempWeightsToWeights(conGrpIter.key()); 00863 ++cntr; 00864 emit progress(cntr, volatileConGrpMap.size()); 00865 } 00866 00867 //Inform other classes about weight change and saved state of network 00868 Globals::getEventRouter()->weightsChangedSlot(); 00869 Globals::getEventRouter()->networkListChangedSlot(); 00870 00871 //Weight saving is complete 00872 weightsSaved = true; 00873 } 00874 00875 00877 void NemoWrapper::setError(const QString& errorMessage){ 00878 currentTaskID = NO_TASK_DEFINED; 00879 error = true; 00880 this->errorMessage = errorMessage; 00881 stopThread = true; 00882 } 00883 00884 00887 void NemoWrapper::setNeuronParametersInNemo(){ 00888 if(neuronGroupID == 0){ 00889 throw SpikeStreamException("Failed to set neuron parameters. NeuronGroupID has not been set."); 00890 } 00891 00892 //Get the neuron group 00893 NeuronGroup* tmpNeurGrp = Globals::getNetwork()->getNeuronGroup(neuronGroupID); 00894 00895 //Set the parameters depending on the type of neuron. 00896 if(tmpNeurGrp->getInfo().getNeuronType().getDescription() == "Izhikevich Excitatory Neuron"){ 00897 setExcitatoryNeuronParameters(tmpNeurGrp); 00898 } 00899 else{ 00900 setInhibitoryNeuronParameters(tmpNeurGrp); 00901 } 00902 } 00903 00904 00906 void NemoWrapper::setExcitatoryNeuronParameters(NeuronGroup* neuronGroup){ 00907 //Get the parameters 00908 float a = neuronGroup->getParameter("a"); 00909 float b = neuronGroup->getParameter("b"); 00910 float c_1 = neuronGroup->getParameter("c_1"); 00911 float d_1 = neuronGroup->getParameter("d_1"); 00912 float d_2 = neuronGroup->getParameter("d_2"); 00913 float v = neuronGroup->getParameter("v"); 00914 float sigma = neuronGroup->getParameter("sigma"); 00915 00916 //Create the random number generator (from: nemo/examples/random1k.cpp) 00917 rng_t rng; 00918 urng_t ranNumGen( rng, boost::uniform_real<double>(0, 1) ); 00919 00920 //Set parameters in the neurons 00921 float c, d, u, rand1, rand2; 00922 NeuronMap::iterator neurGrpEnd = neuronGroup->end(); 00923 for(NeuronMap::iterator iter = neuronGroup->begin(); iter != neurGrpEnd; ++iter){ 00924 //Get random numbers 00925 rand1 = ranNumGen(); 00926 rand2 = ranNumGen(); 00927 00928 //Calculate excitatory neuron parameters 00929 c = v + c_1 * rand1 * rand2; 00930 d = d_1 - d_2 * rand1 * rand2; 00931 u = b * v; 00932 00933 #ifdef DEBUG_PARAMETERS 00934 qDebug()<<"Setting excitatory neuron parameters for neuron "<<iter.key()<<". a="<<a<<"; b="<<b<<"; c="<<c<<"; d="<<d<<"; u="<<u<<"; v="<<v<<"; sigma="<<sigma; 00935 #endif//DEBUG_PARAMETERS 00936 00937 //Set parameters in neuron 00938 checkNemoOutput( 00939 nemo_set_neuron_iz_s( 00940 nemoSimulation, 00941 iter.key(), 00942 a, b, c, d, u, v, sigma 00943 ), 00944 "Failed to set Izhikevich excitatory neuron parameters." 00945 ); 00946 } 00947 } 00948 00949 00951 void NemoWrapper::setInhibitoryNeuronParameters(NeuronGroup* neuronGroup){ 00952 //Extract inhibitory neuron parameters 00953 float a_1 = neuronGroup->getParameter("a_1"); 00954 float a_2 = neuronGroup->getParameter("a_2"); 00955 float b_1 = neuronGroup->getParameter("b_1"); 00956 float b_2 = neuronGroup->getParameter("b_2"); 00957 float d = neuronGroup->getParameter("d"); 00958 float v = neuronGroup->getParameter("v"); 00959 float sigma = neuronGroup->getParameter("sigma"); 00960 00961 //Create the random number generator (from: nemo/examples/random1k.cpp) 00962 rng_t rng; 00963 urng_t ranNumGen( rng, boost::uniform_real<double>(0, 1) ); 00964 00965 //Set parameters in the neurons 00966 float a, b, u, rand1, rand2; 00967 NeuronMap::iterator neurGrpEnd = neuronGroup->end(); 00968 for(NeuronMap::iterator iter = neuronGroup->begin(); iter != neurGrpEnd; ++iter){ 00969 //Get random numbers 00970 rand1 = ranNumGen(); 00971 rand2 = ranNumGen(); 00972 00973 //Calculate inhibitory neuron parameters 00974 a = a_1 + a_2 * rand1; 00975 b = b_1 - b_2 * rand2; 00976 u = b * v; 00977 00978 //Set parameters in neuron FIXME 00979 checkNemoOutput( 00980 nemo_set_neuron_iz_s( 00981 nemoSimulation, 00982 iter.key(), 00983 a, b, v, d, u, v, sigma 00984 ), 00985 "Failed to set Izhikevich inhibitory neuron parameters." 00986 ); 00987 } 00988 } 00989 00990 00992 void NemoWrapper::stepNemo(){ 00993 unsigned *firedArray, numFiredNeurons = 0, numCurrentNeurons = 0; 00994 size_t firedCount; 00995 firingNeuronList.clear(); 00996 00997 //--------------------------------------- 00998 // Step simulation 00999 //--------------------------------------- 01000 //Add inject noise neurons to end of injection vector 01001 if(!injectNoiseMap.isEmpty() || !neuronIDsToFire.isEmpty() || !deviceManagerList.isEmpty()) 01002 numFiredNeurons = addInjectFiringNeuronIDs(); 01003 01004 if(!injectCurrentMap.isEmpty() || !neuronIDCurrentMap.isEmpty() || !deviceManagerList.isEmpty()) 01005 numCurrentNeurons = addInjectCurrentNeuronIDs(); 01006 01007 #ifdef DEBUG_STEP 01008 qDebug()<<"About to step nemo."; 01009 #endif//DEBUG_STEP 01010 checkNemoOutput( 01011 nemo_step( 01012 nemoSimulation, 01013 &injectionPatternVector.front(), 01014 injectionPatternVector.size(), 01015 &injectionCurrentNeurIDVector.front(), 01016 &injectionCurrentVector.front(), 01017 injectionCurrentNeurIDVector.size(), 01018 &firedArray, 01019 &firedCount 01020 ), 01021 "Nemo error on step." ); 01022 #ifdef DEBUG_STEP 01023 qDebug()<<"Nemo successfully stepped."; 01024 #endif//DEBUG_STEP 01025 01026 //Empty noise injection map if we are not sustaining it 01027 if(!sustainNoise) 01028 injectNoiseMap.clear(); 01029 01030 //Clear inject current parameters if we are not sustaining it 01031 if(!sustainCurrent){ 01032 injectCurrentMap.clear(); 01033 } 01034 01035 //Delete pattern if it is not sustained 01036 if(!sustainPattern){ 01037 injectionPatternVector.clear(); 01038 injectionCurrentNeurIDVector.clear(); 01039 injectionCurrentVector.clear(); 01040 } 01041 //Delete neurons added to end of vector from noise or current 01042 else { 01043 if(numFiredNeurons > 0){ 01044 injectionPatternVector.erase(injectionPatternVector.end() - numFiredNeurons, injectionPatternVector.end()); 01045 } 01046 if(numCurrentNeurons > 0){ 01047 injectionCurrentNeurIDVector.erase(injectionCurrentNeurIDVector.end() - numCurrentNeurons, injectionCurrentNeurIDVector.end()); 01048 injectionCurrentVector.erase(injectionCurrentVector.end() - numCurrentNeurons, injectionCurrentVector.end()); 01049 } 01050 } 01051 01052 01053 //--------------------------------------------------------- 01054 // Pass list of firing neurons to other classes 01055 //--------------------------------------------------------- 01056 if(archiveMode || (monitorFiringNeurons && monitor) || !deviceManagerList.isEmpty() || updateFiringNeurons){ 01057 //Add firing neuron ids to list 01058 for(unsigned i=0; i<firedCount; ++i) 01059 firingNeuronList.append(firedArray[i]); 01060 #ifdef DEBUG_STEP 01061 if(firedCount > 0) 01062 qDebug()<<"Number of firing neurons: "<<firedCount; 01063 #endif//DEBUG_STEP 01064 #ifdef TIME_PERFORMANCE 01065 numberOfFiringNeurons += firedCount; 01066 #endif//TIME_PERFORMANCE 01067 01068 //Store firing neurons in database 01069 if(archiveMode){ 01070 archiveDao->addArchiveData(archiveInfo.getID(), timeStepCounter, firingNeuronList); 01071 } 01072 01073 //Pass firing neurons to device managers and step device managers 01074 for(int i=0; i<deviceManagerList.size(); ++i){ 01075 deviceManagerList[i]->setInputNeurons(timeStepCounter, firingNeuronList); 01076 deviceManagerList[i]->step(); 01077 } 01078 } 01079 01080 01081 //----------------------------------------------- 01082 // Extract membrane potential 01083 //----------------------------------------------- 01084 if(monitor && monitorMembranePotential){ 01085 #ifdef DEBUG_STEP 01086 qDebug()<<"About to read membrane potential."; 01087 #endif//DEBUG_STEP 01088 getMembranePotential(); 01089 #ifdef DEBUG_STEP 01090 qDebug()<<"Successfully read membrane potential."; 01091 #endif//DEBUG_STEP 01092 } 01093 01094 01095 //-------------------------------------------- 01096 // Apply STDP 01097 //-------------------------------------------- 01098 if(!volatileConGrpMap.isEmpty()){ 01099 if(timeStepCounter % applySTDPInterval == 0){ 01100 checkNemoOutput( 01101 nemo_apply_stdp(nemoSimulation, stdpReward), 01102 "NeMo error applying STDP" 01103 ); 01104 #ifdef DEBUG_LEARNING 01105 qDebug()<<"Applying STDP. TimeStepCounter="<<timeStepCounter<<"; applySTDPInterval="<<applySTDPInterval; 01106 #endif 01107 } 01108 } 01109 01110 01111 //-------------------------------------------- 01112 // Retrieve weights 01113 //-------------------------------------------- 01114 if(monitorWeights && monitor && (timeStepCounter % applySTDPInterval == 0)){//Same condition as applying STDP 01115 updateNetworkWeights(); 01116 01117 //Inform other classes that weights have changed 01118 Globals::getEventRouter()->weightsChangedSlot(); 01119 } 01120 01121 if(monitor){ 01122 /* Set flag to cause thread to wait for graphics to update. 01123 This is needed even if we are just running a time step counter */ 01124 waitForGraphics = true; 01125 01126 //Inform listening classes that this time step has been processed 01127 if(monitorFiringNeurons) 01128 emit timeStepChanged(timeStepCounter, firingNeuronList); 01129 else if (monitorMembranePotential) 01130 emit timeStepChanged(timeStepCounter, membranePotentialMap); 01131 else 01132 emit(timeStepChanged(timeStepCounter)); 01133 } 01134 01135 //Update time step counter 01136 ++timeStepCounter; 01137 } 01138 01139 01141 void NemoWrapper::unloadNemo(){ 01142 /* Unlock mutex if it is still locked. 01143 need to call try lock in case mutex is unlocked, in which case calling 01144 unlock again may cause a crash */ 01145 mutex.tryLock(); 01146 mutex.unlock(); 01147 01148 runMutex.tryLock(); 01149 runMutex.unlock(); 01150 01151 //Clean up dynamic arrays in volatile connection group map 01152 for(QHash<unsigned, synapse_id*>::iterator conGrpIter = volatileConGrpMap.begin(); conGrpIter != volatileConGrpMap.end(); ++conGrpIter){ 01153 delete conGrpIter.value(); 01154 } 01155 volatileConGrpMap.clear(); 01156 01157 //Clean up sustain noise etc. 01158 sustainNoise = false; 01159 injectNoiseMap.clear(); 01160 sustainCurrent = false; 01161 injectCurrentMap.clear(); 01162 sustainPattern = false; 01163 injectionPatternVector.clear(); 01164 injectionCurrentNeurIDVector.clear(); 01165 injectionCurrentVector.clear(); 01166 01167 simulationLoaded = false; 01168 archiveInfo.reset(); 01169 } 01170 01171 01174 void NemoWrapper::updateNetworkWeights(){ 01175 if(!simulationLoaded){ 01176 throw SpikeStreamException("Failed to update network weights. Simulation not loaded."); 01177 } 01178 01179 //Work through all of the volatile connection groups 01180 for(QHash<unsigned, synapse_id*>::iterator conGrpIter = volatileConGrpMap.begin(); conGrpIter != volatileConGrpMap.end(); ++conGrpIter){ 01181 //Get the volatile connection group and matching array of nemo synapse IDs 01182 ConnectionGroup* tmpConGrp = Globals::getNetwork()->getConnectionGroup(conGrpIter.key()); 01183 synapse_id* synapseIDArray = conGrpIter.value(); 01184 double weightFactor = tmpConGrp->getParameter("weight_factor");//Amount by which weight was multiplied when connection was added to NeMo 01185 01186 //Work through connection group and query volatile connections 01187 float tmpWeight;//Variable passed to NeMo to get weight 01188 unsigned conCntr = 0; 01189 ConnectionIterator conGrpEnd = tmpConGrp->end(); 01190 for(ConnectionIterator conIter = tmpConGrp->begin(); conIter != conGrpEnd; ++conIter){ 01191 #ifdef DEBUG_WEIGHTS 01192 qDebug()<<"About to query weights: nemo synapseID="<<synapseIDArray[conCntr]<<" spikestream synapse id="<<conIter->getID(); 01193 #endif//DEBUG_WEIGHTS 01194 01195 //Query weight 01196 checkNemoOutput( nemo_get_synapse_weight_s(nemoSimulation, synapseIDArray[conCntr], &tmpWeight), "Error getting weights." ); 01197 01198 //Update weight in connection 01199 #ifdef DEBUG_WEIGHTS 01200 qDebug()<<"Old weight: "<<conIter->getTempWeight()<<"; New weight: "<<(tmpWeight / weightFactor); 01201 #endif//DEBUG_WEIGHTS 01202 conIter->setTempWeight(tmpWeight / weightFactor); 01203 01204 #ifdef DEBUG_WEIGHTS 01205 qDebug()<<"TimeStep: "<<timeStepCounter<<"; Weight query complete: weight="<<tmpWeight<<" nemo synapse id="<<synapseIDArray[conCntr]; 01206 #endif//DEBUG_WEIGHTS 01207 01208 //Increase counter for accessing synapse id array 01209 ++conCntr; 01210 } 01211 } 01212 } 01213 01214