SpikeStream Library
0.2
|
00001 //SpikeStream includes 00002 #include "GlobalVariables.h" 00003 #include "NeuronGroup.h" 00004 #include "SpikeStreamException.h" 00005 #include "Util.h" 00006 using namespace spikestream; 00007 00008 //Qt includes 00009 #include <QDebug> 00010 00011 //Other includes 00012 #include <iostream> 00013 using namespace std; 00014 00015 //Initialize static variables 00016 unsigned NeuronGroup::neuronIDCounter = LAST_NEURON_ID + 1; 00017 //unsigned NeuronGroup::neuronIDCounter = 0; 00018 00020 NeuronGroup::NeuronGroup(const NeuronGroupInfo& info){ 00021 this->info = info; 00022 neuronMap = new NeuronMap(); 00023 startNeuronID = 0; 00024 calculateBoundingBox = false; 00025 positionMapBuilt = false; 00026 } 00027 00028 00030 NeuronGroup::~NeuronGroup(){ 00031 //Deletes neuron map and all its dynamically allocated objects 00032 if(neuronMap != NULL){ 00033 clearNeurons(); 00034 delete neuronMap; 00035 } 00036 } 00037 00038 00039 /*--------------------------------------------------------- */ 00040 /*----- PUBLIC METHODS ----- */ 00041 /*--------------------------------------------------------- */ 00042 00045 Neuron* NeuronGroup::addNeuron(float xPos, float yPos, float zPos){ 00046 //Get temporary ID for the neuron - this must be unique and not exist in the current map 00047 unsigned tmpID = getTemporaryID(); 00048 00049 //Fix start neuron id 00050 if(neuronMap->isEmpty()) 00051 startNeuronID = tmpID; 00052 else if(tmpID < startNeuronID) 00053 startNeuronID = tmpID; 00054 00055 //Create neuron class 00056 Neuron* tmpNeuron = new Neuron(tmpID, xPos, yPos, zPos); 00057 00058 //Store neuron class in ID map 00059 if(neuronMap->contains(tmpID)) 00060 throw SpikeStreamException("Automatically generated temporary neuron ID clashes with one in the network. New ID=" + QString::number(tmpID)); 00061 (*neuronMap)[tmpID] = tmpNeuron; 00062 00063 //Finish off 00064 neuronGroupChanged(); 00065 return tmpNeuron; 00066 } 00067 00068 00071 void NeuronGroup::addLayer(int width, int height, int xPos, int yPos, int zPos){ 00072 for(int x=xPos; x < (xPos + width); ++x){ 00073 for(int y=yPos; y < (yPos + height); ++y){ 00074 addNeuron(x, y, zPos); 00075 } 00076 } 00077 neuronGroupChanged(); 00078 } 00079 00080 00082 void NeuronGroup::buildPositionMap(){ 00083 neuronPositionMap.clear(); 00084 00085 //Work through all neurons 00086 NeuronMap::iterator mapEnd = neuronMap->end(); 00087 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00088 //Store link between neuron position and neuron class 00089 uint64_t tmpKey = getPositionKey(iter.value()->getXPos(), iter.value()->getYPos(), iter.value()->getZPos()); 00090 if(neuronPositionMap.contains(tmpKey)) 00091 throw SpikeStreamException("Position key clashes with one in the position map. Key=" + QString::number(tmpKey)); 00092 neuronPositionMap[tmpKey] = iter.value(); 00093 } 00094 00095 //Set flag to record that we have built position map 00096 positionMapBuilt = true; 00097 } 00098 00099 00101 void NeuronGroup::clearNeurons(){ 00102 NeuronMap::iterator endNeuronMap = neuronMap->end(); 00103 for(NeuronMap::iterator iter = neuronMap->begin(); iter != endNeuronMap; ++iter){ 00104 delete iter.value(); 00105 } 00106 neuronMap->clear(); 00107 neuronGroupChanged(); 00108 } 00109 00110 00112 bool NeuronGroup::contains(unsigned int neurID){ 00113 if(neuronMap->contains(neurID)) 00114 return true; 00115 return false; 00116 } 00117 00118 00120 bool NeuronGroup::contains(unsigned int neurID, float x, float y, float z){ 00121 if(!neuronMap->contains(neurID)) 00122 return false;; 00123 if((*neuronMap)[neurID]->getXPos() != x || (*neuronMap)[neurID]->getYPos() != y || (*neuronMap)[neurID]->getZPos() != z) 00124 return false; 00125 return true; 00126 } 00127 00128 00131 Box NeuronGroup::getBoundingBox(){ 00132 //Return current box if nothing has changed about the neuron group 00133 if(!calculateBoundingBox) 00134 return boundingBox; 00135 00136 //Calculate the bounding box 00137 Neuron* tmpNeuron; 00138 bool firstTime = true; 00139 NeuronMap::iterator mapEnd = neuronMap->end();//Saves accessing this function multiple times 00140 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00141 tmpNeuron = iter.value(); 00142 if(firstTime){//Take first neuron as starting point 00143 boundingBox = Box(tmpNeuron->getXPos(), tmpNeuron->getYPos(), tmpNeuron->getZPos(), 00144 tmpNeuron->getXPos(), tmpNeuron->getYPos(), tmpNeuron->getZPos() 00145 ); 00146 firstTime = false; 00147 } 00148 else{//Expand box to include subsequent neurons 00149 if(tmpNeuron->getXPos() < boundingBox.x1) 00150 boundingBox.x1 = tmpNeuron->getXPos(); 00151 if(tmpNeuron->getYPos() < boundingBox.y1) 00152 boundingBox.y1 = tmpNeuron->getYPos(); 00153 if(tmpNeuron->getZPos() < boundingBox.z1) 00154 boundingBox.z1 = tmpNeuron->getZPos(); 00155 00156 if(tmpNeuron->getXPos() > boundingBox.x2) 00157 boundingBox.x2 = tmpNeuron->getXPos(); 00158 if(tmpNeuron->getYPos() > boundingBox.y2) 00159 boundingBox.y2 = tmpNeuron->getYPos(); 00160 if(tmpNeuron->getZPos() > boundingBox.z2) 00161 boundingBox.z2 = tmpNeuron->getZPos(); 00162 } 00163 } 00164 00165 //Return calculated box 00166 calculateBoundingBox = false; 00167 return boundingBox; 00168 } 00169 00170 00172 unsigned NeuronGroup::getID(){ 00173 return info.getID(); 00174 } 00175 00176 00180 Neuron* NeuronGroup::getNearestNeuron(const Point3D& point){ 00181 double minDist = 0, tmpDist; 00182 bool firstTime; 00183 Neuron* closestNeuron = NULL; 00184 NeuronMap::iterator mapEnd = neuronMap->end();//Saves accessing this function multiple times 00185 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00186 tmpDist = iter.value()->getLocation().distance(point); 00187 if(firstTime){ 00188 minDist = tmpDist; 00189 closestNeuron = iter.value(); 00190 firstTime = false; 00191 } 00192 else{ 00193 if(tmpDist < minDist){ 00194 minDist = tmpDist; 00195 closestNeuron = iter.value(); 00196 } 00197 } 00198 } 00199 return closestNeuron; 00200 } 00201 00202 00204 unsigned int NeuronGroup::getNeuronIDAtLocation(const Point3D& point){ 00205 NeuronMap::iterator mapEnd = neuronMap->end();//Saves accessing this function multiple times 00206 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00207 if(iter.value()->getLocation() == point) 00208 return iter.key(); 00209 } 00210 throw SpikeStreamException("No neuron at location "+ point.toString()); 00211 } 00212 00213 00215 Point3D& NeuronGroup::getNeuronLocation(unsigned int neuronID){ 00216 if(!neuronMap->contains(neuronID)){ 00217 this->print(); 00218 throw SpikeStreamException("Neuron ID '" + QString::number(neuronID) + "' could not be found."); 00219 } 00220 return (*neuronMap)[neuronID]->getLocation(); 00221 } 00222 00223 00225 QList<Neuron*> NeuronGroup::getNeurons(const Box& box){ 00226 QList<Neuron*> tmpList; 00227 NeuronMap::iterator mapEnd = neuronMap->end(); 00228 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00229 if( box.contains(iter.value()->getLocation()) ) 00230 tmpList.append(iter.value()); 00231 } 00232 return tmpList; 00233 } 00234 00235 00237 unsigned NeuronGroup::getNeuronTypeID(){ 00238 return getInfo().getNeuronTypeID(); 00239 } 00240 00241 00244 double NeuronGroup::getParameter(const QString &key){ 00245 if(!parameterMap.contains(key)) 00246 throw SpikeStreamException("Cannot find parameter with key: " + key + " in neuron group with ID " + QString::number(info.getID())); 00247 return parameterMap[key]; 00248 } 00249 00250 00255 uint64_t NeuronGroup::getPositionKey(int xPos, int yPos, int zPos){ 00256 if(xPos < 0 || yPos < 0 || zPos < 0) 00257 throw SpikeStreamException("This method currently only works with positive positions."); 00258 00259 //Check positions are in range for this type of encoding 00260 if(xPos > 2097151 || yPos > 2097151 || zPos > 2097151) 00261 throw SpikeStreamException("X, Y or Z position out of range. Must be less than or equal to 2097151."); 00262 00263 //Create key 00264 uint64_t newKey = xPos; 00265 newKey <<= 21; 00266 newKey |= yPos; 00267 newKey <<= 21; 00268 newKey |= zPos; 00269 return newKey; 00270 } 00271 00272 00274 Point3D NeuronGroup::getPointFromPositionKey(uint64_t positionKey){ 00275 uint64_t keyExtractor = 2097151; 00276 float tmpZPos = (float) (positionKey & keyExtractor); 00277 positionKey >>= 21; 00278 float tmpYPos = (float) (positionKey & keyExtractor); 00279 positionKey >>= 21; 00280 float tmpXPos = (float) (positionKey & keyExtractor); 00281 return Point3D(tmpXPos, tmpYPos, tmpZPos); 00282 } 00283 00284 00286 bool NeuronGroup::isWeightless(){ 00287 if(info.getNeuronType().getDescription().toUpper() == "WEIGHTLESS NEURON") 00288 return true; 00289 return false; 00290 } 00291 00292 00294 bool NeuronGroup::parametersSet(){ 00295 if(getInfo().getNeuronType().getParameterCount() == parameterMap.size()) 00296 return true; 00297 return false; 00298 } 00299 00300 00302 void NeuronGroup::print(){ 00303 cout<<"------------- Neuron Group: id="<<info.getID()<<"; description="<<info.getDescription().toStdString(); 00304 cout<<" "<<info.getNeuronType().getDescription().toStdString()<<" -------------"<<endl; 00305 NeuronMap::iterator mapEnd = neuronMap->end(); 00306 for(NeuronMap::iterator iter=neuronMap->begin(); iter != mapEnd; ++iter){ 00307 iter.value()->print(); 00308 } 00309 } 00310 00311 00315 NeuronPositionIterator NeuronGroup::positionBegin(){ 00316 if(!positionMapBuilt) 00317 buildPositionMap(); 00318 return neuronPositionMap.begin(); 00319 } 00320 00321 00325 NeuronPositionIterator NeuronGroup::positionEnd(){ 00326 if(!positionMapBuilt) 00327 buildPositionMap(); 00328 return neuronPositionMap.end(); 00329 } 00330 00331 00333 void NeuronGroup::setID(unsigned int id){ 00334 info.setID(id); 00335 } 00336 00337 00339 void NeuronGroup::setDescription(const QString& description){ 00340 info.setDescription(description); 00341 } 00342 00343 00345 void NeuronGroup::setName(const QString& name){ 00346 info.setName(name); 00347 } 00348 00349 00352 void NeuronGroup::setNeuronMap(NeuronMap* newMap){ 00353 delete neuronMap; 00354 this->neuronMap = newMap; 00355 neuronGroupChanged(); 00356 } 00357 00358 00362 void NeuronGroup::setParameters(QHash<QString, double>& paramMap){ 00363 //Get the neuron type associated with this neuron group 00364 NeuronType neurType = getInfo().getNeuronType(); 00365 QList<ParameterInfo> paramInfoList = neurType.getParameterInfoList(); 00366 if(paramInfoList.size() != paramMap.size()) 00367 throw SpikeStreamException("NeuronGroup: failed to set parameters. Mismatch between number of parameters."); 00368 foreach(ParameterInfo paramInfo, paramInfoList){ 00369 if(!paramMap.contains(paramInfo.getName())) 00370 throw SpikeStreamException("NeuronGroup: failed to set parameters. Missing parameter: " + paramInfo.getName()); 00371 } 00372 00373 //Parameters are ok - store map. 00374 this->parameterMap = paramMap; 00375 } 00376 00377 00379 int NeuronGroup::size(){ 00380 return neuronMap->size(); 00381 } 00382 00383 00384 /*--------------------------------------------------------- */ 00385 /*----- PRIVATE METHODS ----- */ 00386 /*--------------------------------------------------------- */ 00387 00389 unsigned NeuronGroup::getTemporaryID(){ 00390 return ++neuronIDCounter; 00391 } 00392 00393 00395 void NeuronGroup::neuronGroupChanged(){ 00396 calculateBoundingBox = true; 00397 positionMapBuilt = false; 00398 }