SpikeStream Nemo Plugin
0.2
|
00001 //SpikeStream includes 00002 #include "Globals.h" 00003 #include "NemoLoader.h" 00004 #include "NeuronGroup.h" 00005 #include "SpikeStreamSimulationException.h" 00006 #include "SpikeStreamIOException.h" 00007 #include "Util.h" 00008 using namespace spikestream; 00009 00010 //Qt includes 00011 #include <QDebug> 00012 00013 //Other includes 00014 #include <vector> 00015 #include <iostream> 00016 using namespace std; 00017 00018 // Outputs verbose debugging behaviour about the loading of the network. 00019 //#define DEBUG_NEURONS 00020 //#define DEBUG_SYNAPSES 00021 00022 //Neuron type IDs in database. FIXME: WOULD BE BETTER TO USE THE NAME 00023 #define IZHIKEVICH_EXCITATORY_NEURON_ID 1 00024 #define IZHIKEVICH_INHIBITORY_NEURON_ID 2 00025 00026 00028 NemoLoader::NemoLoader(){ 00029 //Open up log file if logging is enabled 00030 #if defined(DEBUG_NEURONS) || defined(DEBUG_SYNAPSES) 00031 logFile = new QFile(Globals::getSpikeStreamRoot() + "/log/NemoLoader.log"); 00032 if(logFile->open(QFile::WriteOnly | QFile::Truncate)) 00033 logTextStream = new QTextStream(logFile); 00034 else{ 00035 throw SpikeStreamIOException("Cannot open log file for NemoLoader."); 00036 } 00037 #endif//DEBUG_NEURONS || DEBUG_SYNAPSES 00038 } 00039 00040 00042 NemoLoader::~NemoLoader(){ 00043 //Clean up log file if logging is enabled 00044 #if defined(DEBUG_NEURONS) || defined(DEBUG_SYNAPSES) 00045 logFile->close(); 00046 delete logFile; 00047 delete logTextStream; 00048 #endif//DEBUG_NEURONS || DEBUG_SYNAPSES 00049 } 00050 00051 00052 /*----------------------------------------------------------*/ 00053 /*----- PUBLIC METHODS -----*/ 00054 /*----------------------------------------------------------*/ 00055 00057 nemo_network_t NemoLoader::buildNemoNetwork(Network* network, QHash<unsigned, synapse_id*>& volatileConGrpMap, const bool* stop){ 00058 //Initialize the nemo network 00059 nemo_network_t nemoNet = nemo_new_network(); 00060 00061 //Check that list of volatie connection is empty 00062 if(!volatileConGrpMap.isEmpty()) 00063 throw SpikeStreamSimulationException("Volatile connection group map should have been cleared when simulation was unloaded."); 00064 00065 //Create the random number generator (from: nemo/examples/random1k.cpp) 00066 rng_t rng; 00067 urng_t ranNumGen( rng, boost::uniform_real<double>(0, 1) );//Constructor of the random number generator 00068 00069 //Calculate progress 00070 QList<NeuronGroup*> neurGrpList = network->getNeuronGroups(); 00071 QList<ConnectionGroup*> conGrpList = network->getConnectionGroups(); 00072 int totalSteps = neurGrpList.size() + conGrpList.size(); 00073 int stepsCompleted = 0; 00074 00075 //Add the neuron groups 00076 for(int i=0; i<neurGrpList.size() && !*stop; ++i){ 00077 unsigned int neurTypeID = neurGrpList.at(i)->getInfo().getNeuronTypeID(); 00078 if(neurTypeID == IZHIKEVICH_EXCITATORY_NEURON_ID) 00079 addExcitatoryNeuronGroup(neurGrpList.at(i), nemoNet, ranNumGen); 00080 else if(neurTypeID == IZHIKEVICH_INHIBITORY_NEURON_ID) 00081 addInhibitoryNeuronGroup(neurGrpList.at(i), nemoNet, ranNumGen); 00082 else 00083 throw SpikeStreamSimulationException("Neuron group type " + QString::number(neurTypeID) + " is not supported by Nemo"); 00084 00085 //Update progress 00086 ++stepsCompleted; 00087 emit progress(stepsCompleted, totalSteps); 00088 } 00089 00090 //Add the connection groups that are not disabled */ 00091 for(int i=0; i<conGrpList.size() && !*stop; ++i){ 00092 if(conGrpList.at(i)->getParameter("Disable") == 0.0) 00093 addConnectionGroup(conGrpList.at(i), nemoNet, volatileConGrpMap); 00094 00095 //Update progress 00096 ++stepsCompleted; 00097 emit progress(stepsCompleted, totalSteps); 00098 } 00099 00100 //Return the new network 00101 return nemoNet; 00102 } 00103 00104 00105 /*----------------------------------------------------------*/ 00106 /*----- PRIVATE METHODS -----*/ 00107 /*----------------------------------------------------------*/ 00108 00110 void NemoLoader::addConnectionGroup(ConnectionGroup* conGroup, nemo_network_t nemoNetwork, QHash<unsigned, synapse_id*>& volatileConGrpMap){ 00111 //Extract parameters 00112 unsigned char learning = 0; 00113 synapse_id* synapseIDArray = NULL; 00114 if(conGroup->getParameter("Learning") != 0.0){ 00115 learning = 1; 00116 synapseIDArray = new synapse_id[conGroup->size()]; 00117 volatileConGrpMap[conGroup->getID()] = synapseIDArray; 00118 } 00119 double weightFactor = conGroup->getParameter("weight_factor"); 00120 00121 //Work through each connection 00122 unsigned conCntr = 0; 00123 nemo_status_t result; 00124 synapse_id newNemoSynapseID; 00125 ConnectionIterator endConGrp = conGroup->end(); 00126 for(ConnectionIterator conIter = conGroup->begin(); conIter != endConGrp; ++conIter){ 00127 //Add synapse 00128 result = nemo_add_synapse(nemoNetwork, conIter->getFromNeuronID(), conIter->getToNeuronID(), conIter->getDelay(), weightFactor * conIter->getWeight(), learning, &newNemoSynapseID); 00129 #ifdef DEBUG_SYNAPSES 00130 (*logTextStream)<<"nemo_add_synapse(nemoNetwork, "<<conIter->getFromNeuronID()<<", "<<conIter->getToNeuronID()<<", "<<conIter->getDelay()<<", "<<(weightFactor * conIter->getWeight())<<", "<<learning<<", "<<newNemoSynapseID<<");"<<endl; 00131 #endif//DEBUG_SYNAPSES 00132 if(result != NEMO_OK) 00133 throw SpikeStreamException("Error code returned from Nemo when adding synapse." + QString(nemo_strerror())); 00134 00135 //Store link between connection group ID and map linking nemo connection IDs and SpikeStream connection IDs 00136 if(learning){ 00137 synapseIDArray[conCntr] = newNemoSynapseID; 00138 ++conCntr; 00139 } 00140 } 00141 } 00142 00143 00145 void NemoLoader::addExcitatoryNeuronGroup(NeuronGroup* neuronGroup, nemo_network_t nemoNetwork, urng_t& ranNumGen){ 00146 //Extract parameters 00147 float a = neuronGroup->getParameter("a"); 00148 float b = neuronGroup->getParameter("b"); 00149 float c_1 = neuronGroup->getParameter("c_1"); 00150 float d_1 = neuronGroup->getParameter("d_1"); 00151 float d_2 = neuronGroup->getParameter("d_2"); 00152 float v = neuronGroup->getParameter("v"); 00153 float sigma = neuronGroup->getParameter("sigma"); 00154 00155 //Add neurons to the network 00156 float c, d, u, rand1, rand2; 00157 for(NeuronMap::iterator iter = neuronGroup->begin(); iter != neuronGroup->end(); ++iter){ 00158 //Calculate random parameters 00159 rand1 = ranNumGen(); 00160 rand2 = ranNumGen(); 00161 c = v + c_1 * rand1 * rand1; 00162 d = d_1 - d_2 * rand2 * rand2; 00163 u = b * v; 00164 00165 //Add the neuron to the network 00166 #ifdef DEBUG_NEURONS 00167 (*logTextStream)<<"nemo_add_neuron(nemoNetwork, "<<iter.value()->getID()<<", "<<a<<", "<<b<<", "<<c<<", "<<d<<", "<<u<<", "<<v<<", "<<sigma<<");"<<endl; 00168 #endif//DEBUG_NEURONS 00169 nemo_status_t result = nemo_add_neuron_iz(nemoNetwork, iter.value()->getID(), a, b, c, d, u, v, sigma); 00170 if(result != NEMO_OK) 00171 throw SpikeStreamException("Error code returned from Nemo when adding neuron." + QString(nemo_strerror())); 00172 } 00173 } 00174 00175 00177 void NemoLoader::addInhibitoryNeuronGroup(NeuronGroup* neuronGroup, nemo_network_t nemoNetwork, urng_t& ranNumGen){ 00178 //Extract parameters 00179 float a_1 = neuronGroup->getParameter("a_1"); 00180 float a_2 = neuronGroup->getParameter("a_2"); 00181 float b_1 = neuronGroup->getParameter("b_1"); 00182 float b_2 = neuronGroup->getParameter("b_2"); 00183 float d = neuronGroup->getParameter("d"); 00184 float v = neuronGroup->getParameter("v"); 00185 float sigma = neuronGroup->getParameter("sigma"); 00186 00187 //Add neurons to the network 00188 float a, b, u, rand1, rand2; 00189 for(NeuronMap::iterator iter = neuronGroup->begin(); iter != neuronGroup->end(); ++iter){ 00190 //Calculate random parameters 00191 rand1 = ranNumGen(); 00192 rand2 = ranNumGen(); 00193 a = a_1 + a_2 * rand1; 00194 b = b_1 - b_2 * rand2; 00195 u = b * v; 00196 00197 //Add neuron to the network 00198 #ifdef DEBUG_NEURONS 00199 (*logTextStream)<<"nemo_add_neuron(nemoNetwork, "<<iter.value()->getID()<<", "<<a<<", "<<b<<", "<<v<<", "<<d<<", "<<u<<", "<<v<<", "<<sigma<<");"<<endl; 00200 #endif//DEBUG_NEURONS 00201 nemo_status_t result = nemo_add_neuron_iz(nemoNetwork, iter.value()->getID(), a, b, v, d, u, v, sigma); 00202 if(result != NEMO_OK) 00203 throw SpikeStreamException("Error code returned from Nemo when adding neuron." + QString(nemo_strerror())); 00204 } 00205 } 00206 00208 void NemoLoader::printConnection(unsigned source, unsigned targets[], unsigned delays[], float weights[], unsigned char is_plastic[], size_t length){ 00209 for(size_t i=0; i<length; ++i){ 00210 if(is_plastic[i]) 00211 cout<<"Connection from: "<<source<<"; to: "<<targets[i]<<"; delay: "<<delays[i]<<"; weight: "<<weights[i]<<" is plastic: true"<<endl; 00212 else 00213 cout<<"Connection from: "<<source<<"; to: "<<targets[i]<<"; delay: "<<delays[i]<<"; weight: "<<weights[i]<<" is plastic: false"<<endl; 00214 } 00215 } 00216 00217