SpikeStream Nemo Plugin  0.2
NemoWrapper.cpp
Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Defines