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