Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

ConnectionManager.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "ConnectionManager.h"
00025 #include "ConnectionType.h"
00026 #include "Utilities.h"
00027 #include "Debug.h"
00028 #include "SpikeStreamMainWindow.h"
00029 
00030 //Qt includes
00031 #include <qstringlist.h>
00032 #include <qregexp.h>
00033 
00034 //Other includes
00035 #include <mysql++.h>
00036 #include <cmath>
00037 #include <iostream>
00038 using namespace std;
00039 using namespace mysqlpp;
00040 
00041 
00042 /*! Exception thrown when there is an error creating connections. */
00043 class CreateConnectionException : public exception{
00044   virtual const char* what() const throw(){
00045     return "Connection creation error.";
00046   }
00047 } createConnectionException;
00048 
00049 
00050 /*! Constructor. */
00051 ConnectionManager::ConnectionManager(DBInterface *netDBInter, DBInterface* devDBInter){
00052         //Store references to database interfaces
00053         networkDBInterface = netDBInter;
00054         deviceDBInterface = devDBInter;
00055 
00056         //Set up a short version of spike stream application reference
00057         spikeStrApp = SpikeStreamMainWindow::spikeStreamApplication;
00058         
00059         //Initialize the random number generator with the seed
00060         srand(randomSeed);
00061         
00062         //Create the progress dialog to provide feedback about connection creation progress
00063         progressDialog =  new QProgressDialog(0, "Creating Connections", true);
00064 }
00065 
00066 
00067 /*! Destructor. */
00068 ConnectionManager::~ConnectionManager(){
00069         #ifdef MEMORY_DEBUG
00070                 cout<<"DELETING CONNECTION MANAGER"<<endl;
00071         #endif//MEMORY_DEBUG
00072 
00073         delete progressDialog;
00074 }
00075 
00076 
00077 //-------------------------------------------------------------------------------------
00078 //---------------------------- PUBLIC METHODS -----------------------------------------
00079 //-------------------------------------------------------------------------------------
00080 
00081 /*! Creates a new connection group of the type specified in the connection holder
00082         Only one connection group of each type can exist between two neuron groups.
00083         Only one from-to and one to-from connection can exist between two neurons. */
00084 int ConnectionManager::createConnections(ConnectionHolder connHolder){
00085         //First check to see if there are any conflicts with existing connection groups
00086         Query query = networkDBInterface->getQuery();
00087         query.reset();
00088         query<<"SELECT ConnGrpID FROM ConnectionGroups WHERE FromNeuronGrpID = "<<connHolder.fromLayerID<<" AND ToNeuronGrpID = "<<connHolder.toLayerID<<" AND ConnType = "<<connHolder.connectionType;
00089         Result connGrpResult = query.store();
00090         if(connGrpResult.size() > 0){
00091                 cerr<<"CONFLICT WITH EXISTING CONNECTION GROUP"<<endl;
00092                 return -1;
00093         }
00094         
00095         /* Next add the connectionGroup entry to the database. This may have to be deleted later 
00096                 if no connections are created, but need the connectionGrpID to create the connections.*/
00097 
00098         /* Create the xml string to hold the parameters of the connection.
00099                 This holds all the information about the connection that is not included elsewhere
00100                 in the connection group table.*/
00101         ostringstream xmlStrStream;
00102         xmlStrStream<<"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
00103         xmlStrStream<<"<connection_parameters>";
00104         for(map<string, double>::iterator iter = connHolder.paramMap.begin(); iter != connHolder.paramMap.end(); ++iter){
00105                 xmlStrStream<<"<parameter>";
00106                 xmlStrStream<<"<description>"<<iter->first<<"</description>";
00107                 xmlStrStream<<"<value>"<<iter->second<<"</value>";
00108                 xmlStrStream<<"</parameter>";
00109         }
00110         xmlStrStream<<"<min_delay>"<<connHolder.minDelay<<"</min_delay>";
00111         xmlStrStream<<"<max_delay>"<<connHolder.maxDelay<<"</max_delay>";
00112         xmlStrStream<<"</connection_parameters>";
00113 
00114         query.reset();
00115         ostringstream strbuf;
00116         strbuf<<"INSERT INTO ConnectionGroups (FromNeuronGrpID, ToNeuronGrpID, ConnType, SynapseType, Parameters) VALUES ("<<connHolder.fromLayerID<<", "<<connHolder.toLayerID<<", "<<connHolder.connectionType<<", "<<connHolder.synapseType<<", \""<<mysqlpp::escape<<xmlStrStream.str()<<"\" )";
00117         query.exec(strbuf.str());
00118         
00119         //Now need to get the automatically generated ConnGrpID so that it can be added to the new connections
00120         query.reset();
00121         query<<"SELECT MAX(ConnGrpID) from ConnectionGroups";
00122         Result grpIDResult = query.store();
00123         Row row(*(grpIDResult.begin()));
00124         connHolder.connectionGrpID = Utilities::getUInt((string)row["MAX(ConnGrpID)"]);
00125         
00126         /*Next create connections. Since there can only be one connection between any two 
00127                 neurons, the connections between layers may be saturated by other types of 
00128                 connection. If at least one pair of neurons are connected, the connection will 
00129                 be created. Otherwise it will be discarded. Connection count is used to check this. */
00130         int connectionCount = 0;
00131         
00132         //Create appropriate connections        
00133         //Work on assumption that ConnectionPropertiesDialog has done checking on compatibility etc.
00134         switch(connHolder.connectionType){
00135                 case (ConnectionType::SimpleCortex):
00136                         createSimpleCortexConns(connHolder, connectionCount);
00137                         break;
00138                 case (ConnectionType::UnstructuredExInhibIntra):
00139                         createUnstructuredExInhibConnections(connHolder, connectionCount);
00140                         break;
00141                 case (ConnectionType::OnCentreOffSurround):
00142                         createOnCentreOffSurroundConns(connHolder, connectionCount);
00143                         break;
00144                 case (ConnectionType::OffCentreOnSurround): 
00145                         createOffCentreOnSurroundConns(connHolder, connectionCount);
00146                         break;
00147                 case (ConnectionType::Unstructured):
00148                         createUnstructuredConns(connHolder, connectionCount);
00149                         break;
00150                 case (ConnectionType::UnstructuredExInhibInter):
00151                         createUnstructuredExInhibConnections(connHolder, connectionCount);
00152                         break;
00153                 case (ConnectionType::Topographic):
00154                         createTopographicConns(connHolder, connectionCount);
00155                         break;
00156                 case (ConnectionType::SIMNOSComponent):
00157                         createSIMNOSComponentConns(connHolder, connectionCount);
00158                         break;  
00159                 case (ConnectionType::Virtual):
00160                         //Nothing to be done here. Virtual connections just have an entry in the connection properties table
00161                 break;
00162                 default:
00163                         cerr<<"CONNECTION TYPE NOT RECOGNIZED"<<endl;
00164                         return -1;
00165         }
00166         
00167         //Delete entry from ConnectionGroup in the database if no connections have been created
00168         if(connectionCount == 0 && connHolder.connectionType != ConnectionType::Virtual){
00169                 //Delete information about this connection group
00170                 query.reset();
00171                 query<<"DELETE FROM ConnectionGroups WHERE ConnGrpID = "<<connHolder.connectionGrpID;
00172                 query.execute();
00173                 return -1;
00174         }
00175         else if(connHolder.connectionType != ConnectionType::Virtual && connHolder.connectionType != ConnectionType::TempVirtual){
00176                 /* Add entry for this layer to the appropriate parameters database */
00177                 //Find the appropriate table
00178                 query.reset();
00179                 query<<"SELECT ParameterTableName FROM SynapseTypes WHERE TypeID = "<<connHolder.synapseType;
00180                 Result tableNameRes = query.store();
00181                 Row tableNameRow (*tableNameRes.begin());//Should only be 1 row
00182         
00183                 //Now add an entry for this connection group to the appropriate table
00184                 query.reset();
00185                 query<<"INSERT INTO "<<(std::string)tableNameRow["ParameterTableName"]<<" (ConnGrpID) VALUES ("<<connHolder.connectionGrpID<<")";
00186                 query.execute();
00187         }
00188 
00189         //Return new connection group ID
00190         return connHolder.connectionGrpID;
00191 }
00192 
00193 
00194 /*! Deletes connections from the ConnectionGroups table and the Connections table. */
00195 void ConnectionManager::deleteConnections(vector<ConnectionHolder> connectionVector){
00196         Query query = networkDBInterface->getQuery();
00197         
00198         vector<ConnectionHolder>::iterator iter;
00199         for(iter = connectionVector.begin(); iter < connectionVector.end(); ++iter){
00200                 //First get the connection ID from the connection table
00201                 query.reset();
00202                 query<<"SELECT ConnGrpID FROM ConnectionGroups WHERE FromNeuronGrpID="<<iter->fromLayerID<<" AND ToNeuronGrpID = "<<iter->toLayerID<<" AND ConnType = "<<iter->connectionType;
00203                 Result result = query.store();
00204                 Row row(*(result.begin()));//ConnGrpID should be unique
00205                 unsigned int connectionGroupID = Utilities::getUInt((std::string)row["ConnGrpID"]);
00206                 
00207                 //Now use connection ID to delete all connections with this ID
00208                 query.reset();
00209                 query<<"DELETE FROM Connections WHERE ConnGrpID = "<<connectionGroupID;
00210                 query.execute();
00211                 
00212                 //Delete information about this connection from the connection table
00213                 query.reset();
00214                 query<<"DELETE FROM ConnectionGroups WHERE ConnGrpID = "<<connectionGroupID;
00215                 query.execute();
00216 
00217                 /*Delete synapse parameters for this connection group
00218                         Simpler just to delete connection group from all parameter tables than to query the
00219                          id and then delete it from the appropriate table */
00220                 query.reset();
00221                 query<<"SELECT ParameterTableName FROM SynapseTypes";
00222                 Result tableNameRes = query.store();
00223                 for(Result::iterator paramTableIter = tableNameRes.begin(); paramTableIter != tableNameRes.end(); ++paramTableIter){
00224                         Row tableNameRow (*paramTableIter);
00225                         query.reset();
00226                         query<<"DELETE FROM "<<(std::string)tableNameRow["ParameterTableName"]<<" WHERE ConnGrpID= "<<connectionGroupID;
00227                         query.execute();
00228                 }
00229         }
00230 }
00231 
00232 
00233 //------------------------------------------------------------------------------------------
00234 //-------------------------------- PRIVATE METHODS -----------------------------------------
00235 //------------------------------------------------------------------------------------------
00236 
00237 /*! Method that checks to see whether a connection between these neurons already exists in the database
00238         At present only a single from, to connection can be made between two neurons.
00239         This could be easily changed at a later point by making the primary key of the Connections table
00240         more complex so that it includes the connection group or synapse type, for example.
00241         In this first version things are being kept simple. */
00242 bool ConnectionManager::connectionExists(mysqlpp::Query &query, unsigned int fromID, unsigned int toID){
00243         query.reset();
00244         query<<"SELECT * FROM Connections WHERE PreSynapticNeuronID = "<<fromID<<" AND PostSynapticNeuronID = "<<toID;
00245         Result result = query.store();
00246         if(result.size() > 0)//Connection does exist
00247                 return true;
00248         return false;//No connection found, return false
00249 }
00250 
00251 
00252 /*! OFF CENTRE ON SURROUND CONNECTIONS
00253         FIXME NOT IMPLEMENTED AT PRESENT. */
00254 void ConnectionManager::createOffCentreOnSurroundConns(ConnectionHolder &, int &){
00255 }
00256 
00257 
00258 /*! ON CENTRE OFF SURROUND CONNECTIONS
00259         Method that creates on centre off surround connections. 
00260         These are rectangular in shape at present. In the future it would be nice to add a circular option
00261         Basic strategy for this function is to work through each of the to neurons, select the neurons
00262         in the from layer that are within the connection area, work through this selection and then
00263         create the connection. */
00264 void ConnectionManager::createOnCentreOffSurroundConns(ConnectionHolder &connHolder, int &connectionCount){
00265         //To begin with get all the information about the from neuron group
00266         Query query = networkDBInterface->getQuery();
00267         query.reset();
00268         query<<"SELECT X, Y, Z, Width, Length FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00269         Result fromNeuronGrpRes = query.store();
00270         Row fromGrpRow(*fromNeuronGrpRes.begin());//Assume that there is only one result
00271         int fromXPos = Utilities::getInt((std::string)fromGrpRow["X"]);
00272         int fromYPos = Utilities::getInt((std::string)fromGrpRow["Y"]);
00273         int fromZPos = Utilities::getInt((std::string)fromGrpRow["Z"]);
00274         int fromGrpWidth_Neur = Utilities::getInt((std::string)fromGrpRow["Width"]);
00275         int fromGrpLength_Neur = Utilities::getInt((std::string)fromGrpRow["Length"]);
00276         
00277         //Next get all information about the to neuron group
00278         query.reset();
00279         query<<"SELECT X, Y, Z, Width, Length, Spacing FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.toLayerID;
00280         Result toNeuronGrpRes = query.store();
00281         Row toGrpRow(*toNeuronGrpRes.begin());//Assume that there is only one result - ID should be unique
00282         int toXPos = Utilities::getInt((std::string)toGrpRow["X"]);
00283         int toYPos = Utilities::getInt((std::string)toGrpRow["Y"]);
00284         int toZPos = Utilities::getInt((std::string)toGrpRow["Z"]);
00285         int toGrpWidth_Neur = Utilities::getInt((std::string)toGrpRow["Width"]);
00286         int toGrpLength_Neur = Utilities::getInt((std::string)toGrpRow["Length"]);
00287         int toGrpSpacing_Pts = Utilities::getInt((std::string)toGrpRow["Spacing"]);
00288         
00289         //Start up the progress dialog. 
00290         progressDialog->reset();
00291         progressDialog->setTotalSteps(toGrpWidth_Neur*toGrpLength_Neur);
00292         progressDialog->setLabelText("Creating connections, please wait");
00293         int progressCount = 0;
00294         
00295         //Get all the parameters for the connection from the parameter map
00296         //These are all rounded to two decimal places to make it easier to do the selection from the 
00297         //from layer when there is no overlap.
00298         double outerWidth = connHolder.paramMap["Outer width"];
00299         Utilities::roundTwoDecimalPlaces(outerWidth);
00300         double outerLength = connHolder.paramMap["Outer length"];
00301         Utilities::roundTwoDecimalPlaces(outerLength); 
00302         double innerWidth = connHolder.paramMap["Inner width"];
00303         Utilities::roundTwoDecimalPlaces(innerWidth);
00304         double innerLength = connHolder.paramMap["Inner length"];
00305         Utilities::roundTwoDecimalPlaces(innerLength);
00306         double overlap = connHolder.paramMap["Overlap"];
00307         Utilities::roundTwoDecimalPlaces(overlap);
00308         
00309         //Layers may need to be rotated at 90 degrees to one another to match up
00310         //Do this by setting different start, finsh and increments for the to layer.
00311         //This looks a bit confusing, but it saves having to repeat the same code twice.
00312         int toStart1, toStart2, toFinish1, toFinish2, toIncrement1, toIncrement2;
00313         if(connHolder.paramMap["Rotate?"] == 1){//To layer has to be rotated wrt the from layer so start at bottom of Y axis and work backwards
00314                 toStart1 = toYPos + (toGrpLength_Neur-1) * toGrpSpacing_Pts;
00315                 toStart2 = toXPos;
00316                 toFinish1 = toYPos - toGrpSpacing_Pts;
00317                 toFinish2 = toXPos + toGrpWidth_Neur * toGrpSpacing_Pts;
00318                 toIncrement1 = -toGrpSpacing_Pts;//Working backwards along the Y axis
00319                 toIncrement2 = toGrpSpacing_Pts;//And forward along X axis
00320         }
00321         else{//Layers can be connected straightforwardly
00322                 toStart1 = toXPos;
00323                 toStart2 = toYPos;
00324                 toFinish1 = toXPos + toGrpWidth_Neur * toGrpSpacing_Pts;//One increment past the width
00325                 toFinish2 = toYPos + toGrpLength_Neur * toGrpSpacing_Pts;//One increment past the length
00326                 toIncrement1 = toGrpSpacing_Pts;
00327                 toIncrement2 = toGrpSpacing_Pts;
00328         }
00329         
00330         //Next create the connections.
00331         //Assume that all neurons are present in the layer, even if some are 'dead'
00332         //Each to neuron has to connect with a subselection of the from layer.
00333         //First set up the variables controlling the from layer selection:
00334         double fromX = fromXPos;
00335         double fromY = fromYPos;
00336 
00337         //Need to work through all the neurons in the to layer jumping forward by the spacing each time
00338         for(int toCounter1 = toStart1; toCounter1 != toFinish1; toCounter1 += toIncrement1){
00339                 for(int toCounter2 = toStart2; toCounter2 != toFinish2; toCounter2 += toIncrement2){
00340                         //Select the neuron at this position in the to layer
00341                         query.reset();
00342                         
00343                         //Need to make changes depending on whether layers are rotated or not.
00344                         if(connHolder.paramMap["Rotate?"] == 0){//In this case toCounter1 is along the X axis and toCounter2 is along the Y axis
00345                                 query<<"SELECT NeuronID FROM Neurons WHERE X = "<<toCounter1<<" AND Y = "<<toCounter2<<" AND Z = "<<toZPos;
00346                         }
00347                         else{//toCounter1 is along the Y axis and toCounter2 is along the X axis
00348                                 query<<"SELECT NeuronID FROM Neurons WHERE X = "<<toCounter2<<" AND Y = "<<toCounter1<<" AND Z = "<<toZPos;
00349                         }
00350                         Result toNeuronRes = query.store();
00351                         if(toNeuronRes.size() != 1){
00352                                 cerr<<"ConnectionManager: To neuron not found at expected position or too many neurons at single location. Number of results: "<<toNeuronRes.size()<<endl;
00353                                 throw createConnectionException;
00354                         }
00355                         Row toNeuronRow(*toNeuronRes.begin());//Have checked that there is only one neuron
00356                         unsigned int toNeuronID = (unsigned int)toNeuronRow["NeuronID"];
00357                         
00358                         //Now work through all of the from neurons
00359                         //Overlap etc. are all rounded to two decimal places. So for each connection select within
00360                         //the layer and then advance it an extra 0.01 to prevent double selection
00361                         
00362                         //First select all the from neurons within the central space to create on centre
00363                         query.reset();
00364                         //Add X stuff to query
00365                         query<<"SELECT NeuronID FROM Neurons WHERE X >= "<<(fromX + outerWidth/2.0 - innerWidth/2.0)<<" AND X <= "<<(fromX + outerWidth/2.0 + innerWidth/2.0);
00366                         //Now add similar Y stuff and Z, which does not change because layers are stacked along z axis
00367                         query<<" AND Y >= "<<(fromY + outerLength/2.0 - innerLength/2.0)<<" AND Y <= "<<(fromY + outerLength/2.0 + innerLength/2.0)<<" AND Z = "<<fromZPos;
00368                         Result fromLayerSelRes1 = query.store();
00369                         
00370                         //Now work through all the selected neurons and create excitatory connections
00371                         for(Result::iterator fromIter = fromLayerSelRes1.begin(); fromIter != fromLayerSelRes1.end(); ++fromIter){
00372                                 Row fromNeuronRow(*fromIter);
00373                                 //Get fromID and check to see if this connection already exists already in the database
00374                                 unsigned int fromNeuronID = (unsigned int)fromNeuronRow["NeuronID"];
00375                                 if(!connectionExists(query, fromNeuronID, toNeuronID)){
00376                                         //Sort out the parameters for the connection
00377                                         unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00378                                         short connectionWeight = getWeight(connHolder.paramMap["Excitation weight"], connHolder.paramMap["Weight range"], connHolder.paramMap["Normal weight distribution?"]);
00379                                         
00380                                         //Add the connection to the database
00381                                         query.reset();
00382                                         query<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID)  VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00383                                         query.execute();
00384                                         ++connectionCount;
00385                                 }
00386                         }
00387                         
00388                         //Now select all neurons within the surround to create off surround
00389                         //The version of MySQL that I am using does not support nested queries and so 
00390                         //have to use a more complex query than I would have liked.
00391                         //Initially will select all neurons within the area of the connetion
00392                         query.reset();
00393                         //Select top chunk of connection area
00394                         query<<"SELECT NeuronID FROM Neurons WHERE ( X >= "<<fromX<<" AND X <= "<<(fromX + outerWidth)<<" AND Y >= "<<fromY<<" AND Y < "<<(fromY + outerLength/2.0 - innerLength/2.0)<<" AND Z = "<<fromZPos<<" ) ";
00395                         //Or bottom chunk of connection area
00396                         query<<"OR ( X >= "<<fromX<<" AND X <= "<<(fromX + outerWidth)<<" AND Y > "<<(fromY + outerLength/2.0 + innerLength/2.0)<<" AND Y <= "<<(fromY + outerLength)<<" AND Z = "<<fromZPos<<" ) ";
00397                         //Or left chunk of connection area
00398                         query<<"OR ( X >= "<<fromX<<" AND X < "<<(fromX + outerWidth/2.0 - innerWidth/2.0)<<" AND Y >= "<<fromY<<" AND Y <= "<<(fromY + outerLength)<<" AND Z = "<<fromZPos<<" ) ";
00399                         //Or right chunk of connection area
00400                         query<<"OR ( X > "<<(fromX + outerWidth/2.0 + innerWidth/2.0)<<" AND X <= "<<(fromX + outerWidth)<<" AND Y >= "<<fromY<<" AND Y <= "<<(fromY + outerLength)<<" AND Z = "<<fromZPos<<" ) ";
00401                         
00402                         Result fromLayerSelRes2 = query.store();
00403                         
00404                         //Now work through all the selected neurons and create inhibitory surround
00405                         for(Result::iterator fromIter = fromLayerSelRes2.begin(); fromIter != fromLayerSelRes2.end(); ++fromIter){
00406                                 Row fromNeuronRow(*fromIter);
00407                                 //Get fromNeuronID and check to see if it already exists in the database
00408                                 unsigned int fromNeuronID = (unsigned int)fromNeuronRow["NeuronID"];
00409                                 if(!connectionExists(query, fromNeuronID, toNeuronID)){
00410                                         //Sort out the parameters for the connection
00411                                         unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00412                                         short connectionWeight = getWeight(connHolder.paramMap["Inhibition weight"], connHolder.paramMap["Weight range"], connHolder.paramMap["Normal weight distribution?"]);
00413 
00414                                         //Add the connection to the database 
00415                                         query.reset();
00416                                         query<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID)  VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00417                                         query.execute();
00418                                         ++connectionCount;
00419                                 }
00420                         }
00421                         //Increase fromY position
00422                         fromY += (outerLength - overlap + 0.01);
00423                         
00424                         //Adjust the progress dialog
00425                         ++progressCount;
00426                         progressDialog->setProgress(progressCount);
00427                         if(progressDialog->wasCancelled())
00428                                 break;
00429                 }
00430                 //Increase fromX position and reset Y position
00431                  fromX += (outerWidth - overlap + 0.01);
00432                  fromY = fromYPos;
00433         }
00434         
00435         //Need to run a check that all from neurons have been connected to. 
00436         //Otherwise could be errors with this.
00437         if(overlap == 0 && connectionCount != (fromGrpWidth_Neur * fromGrpLength_Neur)){
00438                 cerr<<"Possible Connection Error: Overlap is zero and yet not all from layer neurons have been connected to the to layer."<<endl;
00439                 cerr<<"Connection Count = "<<connectionCount<<"; From layer size = "<<(fromGrpWidth_Neur * fromGrpLength_Neur);
00440         }
00441 }
00442 
00443 
00444 /*! Creates topographic connections between this layer and part of the device layer
00445         Each component contains a list of receptor ids and so have to work through these
00446         and make the appropriate connections to the device input layer. */
00447 void ConnectionManager::createSIMNOSComponentConns(ConnectionHolder& connHolder, int &connectionCount){
00448         //Get the width and length of the from neuron group
00449         Query networkQuery = networkDBInterface->getQuery();
00450         networkQuery.reset();
00451         networkQuery<<"SELECT Width, Length FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00452         Result fromSizeRes = networkQuery.store();
00453         Row fromSizeRow (*fromSizeRes.begin());//fromLayerID should be unique
00454         unsigned int fromGrpWidth = Utilities::getUInt((std::string)fromSizeRow["Width"]);
00455         unsigned int fromGrpLength = Utilities::getUInt((std::string)fromSizeRow["Length"]);
00456 
00457         //Get the width and length of the to neuron group
00458         networkQuery.reset();
00459         networkQuery<<"SELECT Width, Length FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.toLayerID;
00460         Result toSizeRes = networkQuery.store();
00461         Row toSizeRow (*toSizeRes.begin());//fromLayerID should be unique
00462         unsigned int toGrpWidth = Utilities::getUInt((std::string)toSizeRow["Width"]);
00463         unsigned int toGrpLength = Utilities::getUInt((std::string)toSizeRow["Length"]);
00464 
00465         //In current implementation from and to group widths should be identical
00466         if(fromGrpWidth != toGrpWidth){
00467                 cerr<<"ConnectionManager: FROM GROUP WIDTH DOES NOT EQUAL TO GROUP WIDTH"<<endl;
00468                 return;
00469         }
00470 
00471         //Get the list of receptors from the SIMNOSComponents database
00472         Query deviceQuery = deviceDBInterface->getQuery();
00473         deviceQuery.reset();
00474         deviceQuery<<"SELECT ReceptorIDs FROM SIMNOSComponents WHERE ComponentID = "<<connHolder.componentID;
00475         Result simnosRes = deviceQuery.store();
00476         Row simnosRow(*simnosRes.begin());//componentID is unique
00477         QString receptorIDString = (std::string)simnosRow["ReceptorIDs"];
00478         QStringList receptorIDStrList = QStringList::split(",", receptorIDString);
00479 
00480         /* Check that the number of receptors does not exceed the length of the new layer.
00481                 There could be less receptors than the length of the new layer since some receptors
00482                 can extend over multiple rows. */
00483         if(receptorIDStrList.size() > fromGrpLength || receptorIDStrList.size() > toGrpLength){
00484                 cerr<<"ConnectionManager: MISMATCH BETWEN NUMBER OF RECEPTOR IDS AND LAYER LENGTH"<<endl;
00485                 return;
00486         }
00487 
00488         /* Create a variable to record which row we are connecting to in the new layer
00489                 and assign this to the first neuron id in the layer */
00490         networkQuery.reset();
00491         networkQuery<<"SELECT MIN(NeuronID) FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00492         Result startFromNeurIDRes = networkQuery.store();
00493         Row startFromNeurIDRow(*startFromNeurIDRes.begin());
00494         unsigned int startFromLayerNeurID = Utilities::getUInt((std::string) startFromNeurIDRow["MIN(NeuronID)"]);
00495 
00496 
00497         /* Create a variable to record which row we are connecting from in the device layer
00498                 and assign this to the first neuron id in the layer */
00499         networkQuery.reset();
00500         networkQuery<<"SELECT MIN(NeuronID) FROM Neurons WHERE NeuronGrpID = "<<connHolder.toLayerID;
00501         Result startToNeurIDRes = networkQuery.store();
00502         Row startToNeurIDRow(*startToNeurIDRes.begin());
00503         unsigned int startToLayerNeurID = Utilities::getUInt((std::string) startToNeurIDRow["MIN(NeuronID)"]);
00504 
00505         /* Work through string list and connect each receptor up to 
00506                 the next part of the new layer 
00507                 NOTE Each receptor is one or more rows in the device input, indicated
00508                 by the StartRow and NumRows values. Currently the colums are ignored. */
00509         unsigned int devGrpNeurID, newGrpNeurID;
00510         unsigned int newGrpRowNum = 0;
00511         for(unsigned int i=0; i<receptorIDStrList.size(); ++i){
00512                 deviceQuery.reset();
00513                 deviceQuery<<"SELECT StartRow, NumRows FROM SIMNOSSpikeReceptors WHERE ReceptorID ="<<receptorIDStrList[i];
00514                 Result recYRes = deviceQuery.store();
00515                 Row recYRow (*recYRes.begin());//Receptor ID should be unique
00516                 unsigned int devStartRow = Utilities::getUInt((std::string)recYRow["StartRow"]);
00517                 unsigned int devNumRows = Utilities::getUInt((std::string)recYRow["NumRows"]);
00518 
00519                 //Set the deviceLayerNeuronID appropriately
00520                 if(connHolder.deviceIsFrom){
00521                         devGrpNeurID = startFromLayerNeurID + fromGrpWidth * devStartRow;
00522                         newGrpNeurID = startToLayerNeurID + toGrpWidth * newGrpRowNum;
00523                 }
00524                 else{
00525                         devGrpNeurID = startToLayerNeurID + toGrpWidth * devStartRow;
00526                         newGrpNeurID = startFromLayerNeurID + fromGrpWidth * newGrpRowNum;
00527                 }
00528 
00529                 //Work through all of the rows in the receptor
00530                 for(unsigned int j=0; j<devNumRows; ++j){
00531                         //Work across row and create connections between the layers
00532                         for(unsigned int i=0; i< fromGrpWidth; ++i){//From and to grp width are the same
00533                                 //Sort out weight and delay
00534                                 unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00535                                 short connectionWeight = getWeight(connHolder.paramMap["Average weight"], connHolder.paramMap["Weight range"], 0); //Random, not normal, distribution
00536         
00537                                 //Create query and add to database
00538                                 networkQuery.reset();
00539                                 if(connHolder.deviceIsFrom){//Connection needs to be from device to new layer
00540                                         networkQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<devGrpNeurID<<", "<<newGrpNeurID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00541                                 }
00542                                 else{//Connection needs to be from new layer to device
00543                                         networkQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<newGrpNeurID<<", "<<devGrpNeurID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00544                                 }
00545                                 networkQuery.execute();
00546                                 ++connectionCount;
00547                                 ++devGrpNeurID;
00548                                 ++newGrpNeurID;
00549                         }
00550                 }
00551 
00552                 //Increase new group row number so next receptor connection will be on a different row
00553                 ++newGrpRowNum;
00554         }
00555 }
00556 
00557 
00558 /*! SIMPLE CORTEX CONNECTIONS
00559         Method that creates cortex style connections within a single layer.
00560         Combines short range excitation with long range inhibition.
00561         Normally distributed random selection of neurons within a circle
00562         Strategy is to select each neuron within the layer and connect appropriateliy to all neurons
00563         within the circle regardless of whether the central neuron is on the edge or not. */
00564 void ConnectionManager::createSimpleCortexConns(ConnectionHolder &connHolder, int &connectionCount){
00565         //Get a query object. This will be used whenever Result and not ResUse is used
00566         Query generalQuery = networkDBInterface->getQuery();
00567         Connection* neighborTmpConnection = networkDBInterface->getNewConnection();
00568         Query neighborConnsQuery = neighborTmpConnection->query();
00569         
00570         //Count the number of neurons and use this to set up the progress dialog
00571         generalQuery.reset();
00572         generalQuery<<"SELECT COUNT(*) FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00573         Result neuronCountRes = generalQuery.store();
00574         Row neuronCountRow(*neuronCountRes.begin());
00575         unsigned int numberOfNeurons = Utilities::getUInt((std::string)neuronCountRow.at(0));
00576         progressDialog->reset();
00577         progressDialog->setTotalSteps(numberOfNeurons);
00578         progressDialog->setLabelText("Creating connections, please wait");
00579         int progressCount = 0;
00580         
00581         //Obtain the connection parameters.
00582         //These are all assumed to have been checked by the connection properties dialog
00583         double excitationRadius = connHolder.paramMap["Excitation radius"];
00584         double inhibitionRadius = connHolder.paramMap["Inhibition radius"];
00585         double overlap = connHolder.paramMap["Overlap"];
00586         double excitationConnDensity = connHolder.paramMap["Excitation connection density"];
00587         double inhibitionConnDensity = connHolder.paramMap["Inhibition connection density"];
00588 
00589         //Get a list of NeuronIDs in the layer and work through it
00590         Connection* neuronsTmpConnection = networkDBInterface->getNewConnection();
00591         Query neuronsQuery = neuronsTmpConnection->query();
00592         neuronsQuery<<"SELECT NeuronID, X, Y, Z FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00593         ResUse layerRes = neuronsQuery.use();//ResUse is much more efficient for large queries
00594         
00595         //Work through the neurons
00596         Row layerRow;
00597         if(layerRes){
00598                 try{
00599                         while( (layerRow = layerRes.fetch_row()) && !progressDialog->wasCancelled()) {
00600                                 int neuronID = Utilities::getInt((std::string)layerRow["NeuronID"]);
00601                                 int xPos = Utilities::getInt((std::string)layerRow["X"]);
00602                                 int yPos = Utilities::getInt((std::string)layerRow["Y"]);
00603                                 int zPos = Utilities::getInt((std::string)layerRow["Z"]);
00604                                 
00605                                 //Now need to select a percentage of the neurons surrounding this neuron within the excitatory radius
00606                                 neighborConnsQuery.reset();
00607                                 neighborConnsQuery<<"SELECT NeuronID, X, Y FROM Neurons WHERE X >= "<<(xPos - excitationRadius)<<" AND X <= "<<(xPos + excitationRadius)<<" ";
00608                                 neighborConnsQuery<<"AND Y >= "<<(yPos - excitationRadius)<<" AND Y <= "<<(yPos + excitationRadius)<<" ";
00609                                 neighborConnsQuery<<"AND Z = "<<zPos<<" AND NeuronGrpID = "<<connHolder.fromLayerID;//This query should give a rectangle around the position
00610                                 ResUse neighborResExcite = neighborConnsQuery.use();
00611                                 Row neighborRow;
00612                                 if(neighborResExcite){
00613                                         try{
00614                                                 while(neighborRow = neighborResExcite.fetch_row()){
00615                                                         int tempNeuronID = Utilities::getInt((std::string)neighborRow["NeuronID"]);
00616                                                         int tempXPos = Utilities::getInt((std::string)neighborRow["X"]);
00617                                                         int tempYPos = Utilities::getInt((std::string)neighborRow["Y"]);
00618                                                         double distance = getDistance(xPos, yPos, tempXPos, tempYPos);
00619                                                         
00620                                                         //Check to see if point lies within excitatory radius and run probability function to create normal distribution of connnections
00621                                                         if((distance <= excitationRadius) && evaluateConnectionProbability(excitationRadius, distance, excitationConnDensity)){
00622                                                                 
00623                                                                 //Create connection
00624                                                                 if(!connectionExists(generalQuery, neuronID, tempNeuronID)){//If connection does not exist already
00625                                                                         
00626                                                                         //Sort out the parameters for the connection
00627                                                                         unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00628                                                                         short connectionWeight = getWeight(connHolder.paramMap["Excitation weight"], connHolder.paramMap["Weight range"], connHolder.paramMap["Normal weight distribution?"]);
00629                                                                         
00630                                                                         //Add the connection to the database
00631                                                                         generalQuery.reset();
00632                                                                         generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<neuronID<<", "<<tempNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00633                                                                         
00634                                                                         generalQuery.execute();
00635                                                                         ++connectionCount;
00636                                                                 }
00637                                                         }
00638                                                 }
00639                                         }
00640                                         catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
00641                                                 //No need to do anything here - this is normal behaviour
00642                                         }
00643                                         catch (const Exception& exception){//Catch any other errors
00644                                                 cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
00645                                         }
00646                                 }
00647                                 else{
00648                                         cerr<<"CANNOT RETRIEVE NEURON DETAILS FOR EXCITATORY CONNECTIONS: "<<neighborConnsQuery.error()<<endl;
00649                                         progressDialog->reset();
00650                                         return;
00651                                 }
00652                                 
00653                                 //Now need to select a percentage of the neurons surrounding this neuron within the inhibitory radius
00654                                 neighborConnsQuery.reset();
00655                                 neighborConnsQuery<<"SELECT NeuronID, X, Y FROM Neurons WHERE X >= "<<(xPos - inhibitionRadius)<<" AND X <= "<<(xPos + inhibitionRadius)<<" ";
00656                                 neighborConnsQuery<<"AND Y >= "<<(yPos - inhibitionRadius)<<" AND Y <= "<<(yPos + inhibitionRadius)<<" ";
00657                                 neighborConnsQuery<<"AND Z = "<<zPos<<" AND NeuronGrpID = "<<connHolder.fromLayerID;//This query should give a rectangle around the position
00658                                 ResUse neighborResInhib = neighborConnsQuery.use();
00659                                 if(neighborResInhib){
00660                                         Row neighborRow;
00661                                         try{
00662                                                 while(neighborRow = neighborResInhib.fetch_row()){
00663                                                         int tempNeuronID = Utilities::getInt((std::string)neighborRow["NeuronID"]);
00664                                                         int tempXPos = Utilities::getInt((std::string)neighborRow["X"]);
00665                                                         int tempYPos = Utilities::getInt((std::string)neighborRow["Y"]);
00666                                                         double distance = getDistance(xPos, yPos, tempXPos, tempYPos);
00667                                                         
00668                                                         //Check to see if point lies within excitatory radius and run probability function to create normal distribution of connnections
00669                                                         //TODO MIGHT WANT TO MAKE IT GREATER THAN INHIBITION RADIUS AS WELL
00670                                                         if((distance >= (excitationRadius - overlap)) && (distance <= inhibitionRadius) && evaluateConnectionProbability(inhibitionRadius, distance, inhibitionConnDensity)){
00671                                                                 
00672                                                                 //Create connection
00673                                                                 if(!connectionExists(generalQuery, neuronID, tempNeuronID)){
00674                                                                         
00675                                                                         //Sort out the parameters for the connection
00676                                                                         unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00677                                                                         short connectionWeight = getWeight(connHolder.paramMap["Inhibition weight"], connHolder.paramMap["Weight range"], connHolder.paramMap["Normal weight distribution?"]);
00678                                                                         
00679                                                                         //Add the connection to the database
00680                                                                         generalQuery.reset();
00681                                                                         generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<neuronID<<", "<<tempNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00682                                                                         
00683                                                                         generalQuery.execute();
00684                                                                         ++connectionCount;
00685                                                                 }
00686                                                         }
00687                                                 }
00688                                         }
00689                                         catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
00690                                                 //No need to do anything here - this is normal behaviour
00691                                         }
00692                                         catch (const Exception& exception){//Catch any other errors
00693                                                 cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
00694                                         }
00695                                 }
00696                                 else{
00697                                         cerr<<"CANNOT RETRIEVE NEURON DETAIL FOR INHIBITORY CONNECTIONSS: "<<neighborConnsQuery.error()<<endl;
00698                                         progressDialog->reset();
00699                                         return;
00700                                 }
00701                                 //Check to see if the progress bar is cancelled
00702                                 if(progressDialog->wasCanceled()){
00703                                         #ifdef CREATE_CONNECTIONS_DEBUG
00704                                                 cout<<"CONNECTION CREATION CANCELLED. NUMBER OF CONNECTIONS CREATED = "<<connectionCount<<endl;
00705                                         #endif//CREATE_CONNECTIONS_DEBUG        
00706                                         return;
00707                                 }
00708                                 
00709                                 //Set the progress in the dialog. This increases with each neuron in the layer
00710                                 ++progressCount;
00711                                 if((progressCount % 10) == 1)
00712                                         progressDialog->setProgress(progressCount);
00713                         }
00714                 }
00715                 catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
00716                         //No need to do anything here - this is normal behaviour
00717                 }
00718                 catch (const Exception& exception){//Catch any other errors
00719                         cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
00720                 }
00721         }
00722         else{
00723                 cerr<<"CANNOT RETRIEVE NEURON GROUP DETAILS: "<<neuronsQuery.error()<<endl;
00724                 progressDialog->reset();
00725         }
00726         //Close connections and reset connections dialog
00727         neighborTmpConnection->close();
00728         neuronsTmpConnection->close();
00729         progressDialog->reset();
00730         #ifdef CREATE_CONNECTIONS_DEBUG
00731                 cout<<"NUMBER OF CONNECTIONS CREATED = "<<connectionCount<<endl;
00732         #endif//CREATE_CONNECTIONS_DEBUG
00733 }
00734 
00735 
00736 /*! Creates connections that are topographically mapped between the two layers
00737         NOTE Only works between layers of identical size. */
00738 void ConnectionManager::createTopographicConns(ConnectionHolder& connHolder, int &connectionCount){
00739         //Behaviour is different depending on the size relationship between the two layers.
00740         Query generalQuery = networkDBInterface->getQuery();
00741         generalQuery<<"SELECT Width, Length FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00742         Result fromLayerRes= generalQuery.store();
00743         Row fromRow(*fromLayerRes.begin());
00744         int fromWidth = Utilities::getInt((std::string)fromRow["Width"]);
00745         int fromLength = Utilities::getInt((std::string)fromRow["Length"]);
00746         
00747         //Get the dimensions of the to group
00748         generalQuery.reset();
00749         generalQuery<<"SELECT Width, Length, X, Y FROM NeuronGroups WHERE NeuronGrpID = "<<connHolder.toLayerID;
00750         Result toLayerRes= generalQuery.store();
00751         Row toRow(*toLayerRes.begin());
00752         int toWidth = Utilities::getInt((std::string)toRow["Width"]);
00753         int toLength = Utilities::getInt((std::string)toRow["Length"]);
00754         int toStartX = Utilities::getInt((std::string)toRow["X"]);
00755         int toStartY = Utilities::getInt((std::string)toRow["Y"]);
00756 
00757         /* If layers are the same size, use a simple method that works through the two layers in parallel.*/
00758         if(fromWidth == toWidth && fromLength == toLength && connHolder.paramMap["Overlap"] == 0.0){
00759                 //Get two result sets holding the neuron ids of the two layers
00760                 generalQuery.reset();
00761                 generalQuery<<"SELECT NeuronID FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID<<" ORDER BY NeuronID";
00762                 Result fromLayerResult = generalQuery.store();
00763                 generalQuery.reset();
00764                 generalQuery<<"SELECT NeuronID FROM Neurons WHERE NeuronGrpID = "<<connHolder.toLayerID<<" ORDER BY NeuronID";
00765                 Result toLayerResult = generalQuery.store();
00766         
00767                 //Double check that they are the same length
00768                 if(fromLayerResult.size() != toLayerResult.size()){
00769                         cerr<<"ConnectionManager: TOPOGRAPHIC CONNECTIONS: FROM LAYER SIZE DOES NOT MATCH TO LAYER SIZE"<<endl;
00770                         return;
00771                 }
00772 
00773                 //Set up progress count
00774                 progressDialog->reset();
00775                 progressDialog->setTotalSteps(fromLayerResult.size());
00776                 progressDialog->setLabelText("Creating connections, please wait");
00777                 int progressCount = 0;
00778         
00779                 //Work through the results in parallel connecting up each of the neurons
00780                 Result::iterator fromIter = fromLayerResult.begin();
00781                 Result::iterator toIter = toLayerResult.begin();
00782                 while((fromIter != fromLayerResult.end())  && !progressDialog->wasCancelled()){
00783                         Row fromRow(*fromIter);
00784                         unsigned int fromNeuronID = Utilities::getUInt((std::string)fromRow["NeuronID"]);
00785                         Row toRow(*toIter);
00786                         unsigned int toNeuronID = Utilities::getUInt((std::string)toRow["NeuronID"]);
00787         
00788                         //Create connection between from and to neuron
00789                         if(!connectionExists(generalQuery, fromNeuronID, toNeuronID)){//If connection does not exist already
00790                                 //Sort out the parameters for the connection
00791                                 unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00792                                 short connectionWeight = getWeight(connHolder.paramMap["Average weight"], connHolder.paramMap["Weight range"], 0); //Random, not normal, distribution
00793         
00794                                 //Add the connection to the database
00795                                 generalQuery.reset();
00796                                 generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00797                                 
00798                                 generalQuery.execute();
00799                                 ++connectionCount;
00800                         }
00801         
00802                         //Set the progress in the dialog. This increases with each neuron in the layer
00803                         ++progressCount;
00804                         if((progressCount % 100) == 1){
00805                                 progressDialog->setProgress(progressCount);
00806                                 spikeStrApp->processEvents();
00807                         }
00808         
00809                         ++fromIter;
00810                         ++toIter;
00811                 }
00812                 //Clear progress dialog
00813                 progressDialog->reset();
00814         }
00815         /* Layers are different sizes or there is overlap specified. */
00816         else{
00817                 //Set up progress count
00818                 progressDialog->reset();
00819                 progressDialog->setTotalSteps(fromWidth * fromLength);
00820                 progressDialog->setLabelText("Creating connections, please wait");
00821                 spikeStrApp->processEvents();
00822                 int progressCount = 0;
00823 
00824                 /* Calculate the from and to connection width and length. */
00825                 int fromConnAreaWidth, fromConnAreaLength, toConnAreaWidth, toConnAreaLength;
00826                 if(connHolder.paramMap["Rotate"] == 0.0){//No rotation of layers
00827                         if(fromWidth > toWidth){
00828                                 fromConnAreaWidth = fromWidth / toWidth;
00829                                 toConnAreaWidth = 1;
00830                         }
00831                         else{
00832                                 fromConnAreaWidth = 1;
00833                                 toConnAreaWidth = toWidth / fromWidth;//Will equal 1 if they are the same
00834                         }
00835                         if(fromLength > toLength){
00836                                 fromConnAreaLength = fromLength / toLength;
00837                                 toConnAreaLength = 1;
00838                         }
00839                         else{
00840                                 fromConnAreaLength = 1;
00841                                 toConnAreaLength = toLength / fromLength;//Will equal 1 if they are the same
00842                         }
00843                 }
00844                 else{//In rotation mode
00845                         if(fromWidth > toLength){
00846                                 fromConnAreaWidth = fromWidth / toLength;
00847                                 toConnAreaLength = 1;
00848                         }
00849                         else{
00850                                 fromConnAreaWidth = 1;
00851                                 toConnAreaLength = toLength / fromWidth;//Will equal 1 if they are the same
00852                         }
00853                         if(fromLength > toWidth){
00854                                 fromConnAreaLength = fromLength / toWidth;
00855                                 toConnAreaWidth= 1;
00856                         }
00857                         else{
00858                                 fromConnAreaLength = 1;
00859                                 toConnAreaWidth = toWidth / fromLength;//Will equal 1 if they are the same
00860                         }
00861                 }
00862 
00863                 //Convert overlap into an integer
00864                 int overlap = (int)rint(connHolder.paramMap["Overlap"]);
00865 
00866                 //Create connections by working through the neurons in the from layer
00867                 //Get the start neuron from ID 
00868                 generalQuery.reset();
00869                 generalQuery<<"SELECT MIN(NeuronID) FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00870                 Result startNeurIDResult = generalQuery.store();
00871                 Row startNeurIDRow(*startNeurIDResult.begin());//Should only be one row
00872                 unsigned int fromStartID = Utilities::getUInt((std::string)startNeurIDRow["MIN(NeuronID)"]);
00873 
00874                 //Create a temporary query whose results can be used rather than stored.
00875                 Connection* toNeuronsConnection = networkDBInterface->getNewConnection();
00876                 Query toNeuronsQuery = toNeuronsConnection->query();
00877 
00878                 //Work through the neurons in the from layer
00879                 for(int fromYPos = 0; fromYPos < fromLength; ++fromYPos){
00880                         for(int fromXPos = 0; fromXPos < fromWidth; ++fromXPos){
00881                                 //Calculate the from neuron id
00882                                 unsigned int fromNeuronID = fromXPos + fromYPos*fromWidth + fromStartID;
00883 
00884                                 //Find all of the neurons in the to layer that this from neuron should connect to
00885                                 int minToX, maxToX, minToY, maxToY;
00886                                 if(connHolder.paramMap["Rotate"] == 0.0){
00887                                         minToX = (fromXPos / fromConnAreaWidth) * toConnAreaWidth + toStartX - overlap;
00888                                         maxToX = minToX + toConnAreaWidth + 2*overlap;
00889                                         minToY = (fromYPos / fromConnAreaLength) * toConnAreaLength + toStartY - overlap;
00890                                         maxToY = minToY + toConnAreaLength + 2*overlap;
00891                                 }
00892                                 else{
00893                                         minToX = (fromYPos / fromConnAreaLength) * toConnAreaWidth + toStartX - overlap;
00894                                         maxToX = minToX + toConnAreaWidth + 2*overlap;
00895                                         minToY = (fromXPos / fromConnAreaWidth) * toConnAreaLength + toStartY - overlap;
00896                                         maxToY = minToY + toConnAreaLength + 2*overlap;
00897                                 }
00898 
00899                                 //Query for neurons in the to layer that lie within the appropriate area
00900                                 toNeuronsQuery.reset();
00901                                 toNeuronsQuery<<"SELECT NeuronID FROM Neurons WHERE X >= "<<minToX<<" AND X < "<<maxToX<<" ";
00902                                 toNeuronsQuery<<"AND Y >= "<<minToY<<" AND Y < "<<maxToY<<" AND NeuronGrpID = "<<connHolder.toLayerID;//Double check to use neuron group id although it is not strictly necessary
00903                                 ResUse toNeuronsRes= toNeuronsQuery.use();
00904                                 if(toNeuronsRes){
00905                                         Row toNeuronsRow;
00906                                         try{
00907                                                 while(toNeuronsRow = toNeuronsRes.fetch_row()){
00908                                                         //Get the to neuron id
00909                                                         unsigned int toNeuronID = Utilities::getInt((std::string)toNeuronsRow["NeuronID"]);
00910                                                         
00911                                                         //Create connection
00912                                                         if(!connectionExists(generalQuery, fromNeuronID, toNeuronID)){
00913                                                                         
00914                                                                 //Sort out the parameters for the connection
00915                                                                 unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
00916                                                                 short connectionWeight = getWeight(connHolder.paramMap["Average weight"], connHolder.paramMap["Weight range"], 0); //Random, not normal, distribution
00917                 
00918                                                                 //Add the connection to the database
00919                                                                 generalQuery.reset();
00920                                                                 generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
00921                                                                 
00922                                                                 generalQuery.execute();
00923                                                                 ++connectionCount;
00924 
00925                                                                 //Set the progress in the dialog. This increases with each neuron in the layer
00926                                                                 ++progressCount;
00927                                                                 if((progressCount % 100) == 1){
00928                                                                         progressDialog->setProgress(progressCount);
00929                                                                         spikeStrApp->processEvents();
00930                                                                 }
00931                                                         }
00932                                                 }
00933                                         }
00934                                         catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
00935                                                 //No need to do anything here - this is normal behaviour
00936                                         }
00937                                         catch (const Exception& exception){//Catch any other errors
00938                                                 cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
00939                                         }
00940                                 }
00941                         }
00942                 }
00943                 //Close the temporary connection
00944                 toNeuronsConnection->close();
00945 
00946                 //Clear progress dialog
00947                 progressDialog->reset();
00948         }
00949 
00950         #ifdef CREATE_CONNECTIONS_DEBUG
00951                 cout<<"NUMBER OF CONNECTIONS CREATED = "<<connectionCount<<endl;
00952         #endif//CREATE_CONNECTIONS_DEBUG
00953 }
00954 
00955 
00956 /*! Creates an unstructured set of connections selected at random between two layers.
00957         Works through each of the neurons in the from layer and selects a random subset of 
00958         neurons to connect to in the to layer. */
00959 void ConnectionManager::createUnstructuredConns(ConnectionHolder& connHolder, int &connectionCount){
00960         //Get the number of neurons in to neuron group and start neuronID
00961         Query generalQuery = networkDBInterface->getQuery();
00962         generalQuery.reset();
00963         generalQuery<<"SELECT MIN(NeuronID), MAX(NeuronID) FROM Neurons WHERE NeuronGrpID = "<<connHolder.toLayerID;
00964         Result toNeuronGrpRes = generalQuery.store();
00965         Row toGrpRow(*toNeuronGrpRes.begin());//Assume that there is only one result
00966         unsigned int startNeuronID = Utilities::getUInt((std::string)toGrpRow["MIN(NeuronID)"]);
00967         unsigned int endNeuronID = Utilities::getUInt((std::string)toGrpRow["MAX(NeuronID)"]);
00968 
00969         /*Work through all the from neurons. 
00970                 For each neuron connect to a random selection of the to neurons */
00971 
00972         //Count the number of neurons and use this to set up the progress dialog
00973         generalQuery.reset();
00974         generalQuery<<"SELECT COUNT(*) FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00975         Result neuronCountRes = generalQuery.store();
00976         Row neuronCountRow(*neuronCountRes.begin());
00977         unsigned int numberOfFromNeurons = Utilities::getUInt((std::string)neuronCountRow["COUNT(*)"]);
00978         progressDialog->reset();
00979         
00980         unsigned int connectionCountEstimate = numberOfFromNeurons * (unsigned int)rint(connHolder.paramMap["Connection density"] * (double)(endNeuronID - startNeuronID));
00981 
00982         progressDialog->setTotalSteps(connectionCountEstimate);
00983         progressDialog->setLabelText("Creating connections, please wait");
00984         spikeStrApp->processEvents();
00985 
00986         Connection* neuronsTmpConnection = networkDBInterface->getNewConnection();
00987         Query neuronsQuery = neuronsTmpConnection->query();
00988         neuronsQuery<<"SELECT NeuronID FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
00989         ResUse neuronsRes = neuronsQuery.use();//ResUse is much more efficient for large queries
00990         
00991         //Work through the from neurons
00992         Row neuronsRow;
00993         if(neuronsRes){
00994                 try{
00995                         while ( (neuronsRow = neuronsRes.fetch_row()) && !progressDialog->wasCancelled()) {
00996                                 int fromNeuronID = Utilities::getInt((std::string)neuronsRow["NeuronID"]);
00997         
00998                                 //Get a vector with a randomly selected list of to neuron ids
00999                                 vector<unsigned int> ranSelVect;
01000                                 fillRandomSelectionVector(ranSelVect, startNeuronID, endNeuronID, connHolder.paramMap["Connection density"]);
01001                                 for(vector<unsigned int>::iterator iter = ranSelVect.begin(); iter != ranSelVect.end()&& !progressDialog->wasCancelled(); ++iter){
01002                                         unsigned int toNeuronID = *iter;
01003                                         //Create connection
01004                                         if(!connectionExists(generalQuery, fromNeuronID, toNeuronID)){//If connection does not exist already
01005                                                 //Sort out the parameters for the connection
01006                                                 unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
01007                                                 short connectionWeight = getWeight(connHolder.paramMap["Average weight"], connHolder.paramMap["Weight range"], 0); //Random, not normal, distribution
01008                                                 
01009                                                 //Add the connection to the database
01010                                                 generalQuery.reset();
01011                                                 generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
01012                                                 
01013                                                 generalQuery.execute();
01014                                                 ++connectionCount;
01015 
01016                                                 //Set the progress in the dialog. This increases with each neuron in the layer
01017                                                 if((connectionCount % 100) == 1){
01018                                                         progressDialog->setProgress(connectionCount);
01019                                                         spikeStrApp->processEvents();
01020                                                 }
01021                                         }
01022                                 }
01023                         }
01024                 }
01025                 catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
01026                         //No need to do anything here - this is normal behaviour
01027                 }
01028                 catch (const Exception& exception){//Catch any other errors
01029                         cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
01030                 }
01031         }       
01032         else{
01033                 #ifdef CREATE_CONNECTIONS_DEBUG
01034                         cerr<<"CANNOT RETRIEVE NEURON DETAILS: "<<neuronsQuery.error()<<endl;
01035                 #endif//CREATE_CONNECTIONS_DEBUG
01036                 progressDialog->reset();
01037         }
01038         neuronsTmpConnection->close();
01039         progressDialog->reset();
01040         #ifdef CREATE_CONNECTIONS_DEBUG
01041                 cout<<"NUMBER OF CONNECTIONS CREATED = "<<connectionCount<<endl;
01042         #endif//CREATE_CONNECTIONS_DEBUG
01043 }
01044 
01045 /*! Creates unstructured connections in which each neuron either makes excitatory connections
01046         or inhibitory connections. Similar to the basic unstructured method. */
01047 void ConnectionManager::createUnstructuredExInhibConnections(ConnectionHolder& connHolder, int& connectionCount){
01048         //Get the number of neurons in to neuron group and start neuronID
01049         Query generalQuery = networkDBInterface->getQuery();
01050         generalQuery.reset();
01051         generalQuery<<"SELECT MIN(NeuronID), MAX(NeuronID) FROM Neurons WHERE NeuronGrpID = "<<connHolder.toLayerID;
01052         Result toNeuronGrpRes = generalQuery.store();
01053         Row toGrpRow(*toNeuronGrpRes.begin());//Assume that there is only one result
01054         unsigned int startNeuronID = Utilities::getUInt((std::string)toGrpRow["MIN(NeuronID)"]);
01055         unsigned int endNeuronID = Utilities::getUInt((std::string)toGrpRow["MAX(NeuronID)"]);
01056 
01057         /*Work through all the from neurons. 
01058                 For each neuron connect to a random selection of the to neurons */
01059 
01060         //Count the number of neurons and use this to set up the progress dialog
01061         generalQuery.reset();
01062         generalQuery<<"SELECT COUNT(*) FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
01063         Result neuronCountRes = generalQuery.store();
01064         Row neuronCountRow(*neuronCountRes.begin());
01065         unsigned int numberOfFromNeurons = Utilities::getUInt((std::string)neuronCountRow["COUNT(*)"]);
01066         progressDialog->reset();
01067         
01068         //Add the excitatory connections to the estimate 
01069         unsigned int connectionCountEstimate = numberOfFromNeurons * (unsigned int)rint((connHolder.paramMap["Excitatory percentage"] / 100.0) * connHolder.paramMap["Excitation connection prob"] * (double)(endNeuronID - startNeuronID));
01070 
01071         //Add the inhibitory connections to the estimate
01072         connectionCountEstimate += numberOfFromNeurons * (unsigned int)rint((1.0 - (connHolder.paramMap["Excitatory percentage"] / 100.0) ) * connHolder.paramMap["Inhibition connection prob"] * (double)(endNeuronID - startNeuronID));
01073 
01074         //Set up progress dialog with this estimate
01075         progressDialog->setTotalSteps(connectionCountEstimate);
01076         progressDialog->setLabelText("Creating connections, please wait");
01077         spikeStrApp->processEvents();
01078 
01079         Connection* neuronsTmpConnection = networkDBInterface->getNewConnection();
01080         Query neuronsQuery = neuronsTmpConnection->query();
01081         neuronsQuery<<"SELECT NeuronID FROM Neurons WHERE NeuronGrpID = "<<connHolder.fromLayerID;
01082         ResUse neuronsRes = neuronsQuery.use();//ResUse is much more efficient for large queries
01083         
01084         //Work through the from neurons
01085         Row neuronsRow;
01086         if(neuronsRes){
01087                 try{
01088                         while ( (neuronsRow = neuronsRes.fetch_row()) && !progressDialog->wasCancelled()) {
01089                                 int fromNeuronID = Utilities::getInt((std::string)neuronsRow["NeuronID"]);
01090 
01091                                 /* Decide whether this is an excitatory or inhibitory neuron.*/
01092                                 bool excitatoryNeuron = isExcitatoryNeuron(fromNeuronID, connHolder.paramMap["Excitatory percentage"]);
01093         
01094                                 //Get a vector with a randomly selected list of to neuron ids
01095                                 vector<unsigned int> ranSelVect;
01096                                 if(excitatoryNeuron)
01097                                         fillRandomSelectionVector(ranSelVect, startNeuronID, endNeuronID, connHolder.paramMap["Excitation connection prob"]);
01098                                 else
01099                                         fillRandomSelectionVector(ranSelVect, startNeuronID, endNeuronID, connHolder.paramMap["Inhibition connection prob"]);
01100 
01101                                 for(vector<unsigned int>::iterator iter = ranSelVect.begin(); iter != ranSelVect.end()&& !progressDialog->wasCancelled(); ++iter){
01102                                         unsigned int toNeuronID = *iter;
01103                                         //Create connection
01104                                         if(!connectionExists(generalQuery, fromNeuronID, toNeuronID)){//If connection does not exist already
01105                                                 //Sort out the parameters for the connection
01106                                                 unsigned short connectionDelay = getDelay(connHolder.minDelay, connHolder.maxDelay);
01107                                                 
01108                                                 short connectionWeight;
01109                                                 if(excitatoryNeuron)
01110                                                         connectionWeight = getWeight(connHolder.paramMap["Excitation weight"], connHolder.paramMap["Excitation weight range"], 0); //Random, not normal, distribution
01111                                                 else
01112                                                         connectionWeight = getWeight(connHolder.paramMap["Inhibition weight"], connHolder.paramMap["Inhibition weight range"], 0); //Random, not normal, distribution
01113 
01114                                                 //Add the connection to the database
01115                                                 generalQuery.reset();
01116                                                 generalQuery<<"INSERT INTO Connections (PreSynapticNeuronID, PostSynapticNeuronID, Delay, Weight, ConnGrpID) VALUES ("<<fromNeuronID<<", "<<toNeuronID<<", "<<connectionDelay<<", "<<connectionWeight<<", "<<connHolder.connectionGrpID<<")";
01117                                                 
01118                                                 generalQuery.execute();
01119                                                 ++connectionCount;
01120 
01121                                                 //Set the progress in the dialog. This increases with each neuron in the layer
01122                                                 if((connectionCount % 100) == 1){
01123                                                         progressDialog->setProgress(connectionCount);
01124                                                         spikeStrApp->processEvents();
01125                                                 }
01126                                         }
01127                                 }
01128                         }
01129                 }
01130                 catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
01131                         //No need to do anything here - this is normal behaviour
01132                 }
01133                 catch (const Exception& exception){//Catch any other errors
01134                         cerr<<"ConnectionManager: UNRECOGNIZED EXCEPTION: "<<exception.what()<<endl;
01135                 }
01136         }       
01137         else{
01138                 #ifdef CREATE_CONNECTIONS_DEBUG
01139                         cerr<<"CANNOT RETRIEVE NEURON DETAILS: "<<neuronsQuery.error()<<endl;
01140                 #endif//CREATE_CONNECTIONS_DEBUG
01141                 progressDialog->reset();
01142         }
01143         neuronsTmpConnection->close();
01144         progressDialog->reset();
01145         #ifdef CREATE_CONNECTIONS_DEBUG
01146                 cout<<"NUMBER OF CONNECTIONS CREATED = "<<connectionCount<<endl;
01147         #endif//CREATE_CONNECTIONS_DEBUG
01148 }
01149 
01150 
01151 /*! For cortex connections want to create a normally distributed connection pattern where neurons 
01152         that are closest to the connecting neuron are most likely to get connected and neurons closest
01153         to the radius are least likely to be connected. This method evaluates whether the connection 
01154         should be created depending on its distance from the neuron. Also has a control 
01155         (connectionDensity) which varies this probability. Should create a normal distribution of 
01156         connections surrounding neuron. */
01157 bool ConnectionManager::evaluateConnectionProbability(double radius, double distance, double connectionDensity){
01158         //Get normally distributed random number
01159         double normRan = getNormalRandom();
01160         
01161         //Limit it to +/- 3
01162         if(normRan < -3.0)
01163                 normRan =-3.0;
01164         else if(normRan > 3.0)
01165                 normRan = 3.0;
01166                 
01167         //Normal random number now varies between -3 and +3 so need to make it fit into the radius range
01168         normRan *= (radius / 3.0);
01169         
01170         //Want a positive number to make comparison easier
01171         if(normRan < 0.0)
01172                 normRan *= -1.0;
01173                 
01174         //Minimun distance between neurons is 1, so need to add 1 to normRan or most connections will be lost
01175         ++normRan;
01176         
01177         //Divide distance by connection density.
01178         //If Connection density is greater than 1 this will reduce the distance and increase the probability that normRan > distance
01179         //If connection density is less than 1 this will increase the distance and reduce the probability that normRan > distance
01180         distance /= connectionDensity;
01181         
01182         //Should now have a number that is between 0 and radius and much more likely to be closer to 0 than to radius
01183         //In first version will accept connection if normRan is less than the actual distance.
01184         //The shorter the distance, the more likely this is to occur. Will have to see how this works in practice
01185         if(normRan >= distance)
01186                 return true;
01187         return false;
01188 }
01189 
01190 
01191 /*! Creates a list of to neurons to connect to. 
01192         A random number is generated and if this is greater than the connection density * ran max,
01193         then the neuronID is added to the vector */
01194 void ConnectionManager::fillRandomSelectionVector(vector<unsigned int> &ranSelVect, unsigned int startNeuronID, unsigned int endNeuronID, double connectionDensity){
01195         int threshold = (int)(connectionDensity * (double)RAND_MAX);
01196         for(unsigned int i=startNeuronID; i<= endNeuronID; ++i){
01197                 if(rand() < threshold)
01198                         ranSelVect.push_back(i);
01199         }
01200 }
01201 
01202 
01203 /*! Generates the delay for a connection.
01204         Returns a positive random number between minDelay and maxDelay. */
01205 unsigned short ConnectionManager::getDelay(unsigned short minDelay, unsigned short maxDelay){
01206         int delayDifference = maxDelay - minDelay;
01207         if(delayDifference < 0){
01208                 cerr<<"ConnectionManager: Max delay should be greater than min delay"<<endl;
01209                 throw createConnectionException;
01210         }
01211         else if(delayDifference == 0)//A precise figure has been set for the delay
01212                 return minDelay;
01213         else{//Need to return a random number between minDelay and maxDelay
01214                 int randomNum = rand();
01215                 double randomDelayDoub = (double)minDelay + (double)randomNum *((double)delayDifference / (double)RAND_MAX);
01216                 int randomDelayInt = (int)rint(randomDelayDoub);
01217 
01218                 #ifdef DELAY_DEBUG
01219                         cout<<"RANDOM NUMBER IS: "<<randomNum<<" RANDOM DELAY IS: "<<randomDelayInt<<endl;//Check that it is approximately random
01220                 #endif//DELAY_DEBUG
01221 
01222                 //Do a final check on the delay
01223                 if(randomDelayInt > 255){
01224                         cerr<<"ConnectionManager: Delay cannot exceed 255!"<<endl;
01225                         throw createConnectionException;
01226                 }
01227                 return randomDelayInt;
01228         }
01229 }
01230 
01231 
01232 /*! Returns the distance between point 1 and point 2 using Pythagoras. */
01233 double ConnectionManager::getDistance(int xPos1, int yPos1, int xPos2, int yPos2){
01234         double distanceSquared = pow((double)xPos1 - (double) xPos2, 2.0) + pow((double)yPos1 - (double)yPos2, 2.0);
01235         return sqrt(distanceSquared);
01236 }
01237 
01238 
01239 /*! Returns a normally distributed random number with standar deviation = 1
01240         Uses Box-Muller method to generate values
01241         Code adapted from http://www.csit.fsu.edu/~burkardt/cpp_src/random_data/random_data.html. */
01242 double ConnectionManager::getNormalRandom(){
01243         double PI = 3.141592653589793;
01244         double rand1, rand2;
01245         static int used = 0;
01246         double x;
01247         static double y = 0.0;
01248         //  If we've used an even number of values so far, generate two more, return one and save one.
01249         if (( used % 2 ) == 0 ){
01250         for ( ; ; ){
01251                         rand1 = (double)rand()/(double)RAND_MAX;
01252                         if ( rand1 != 0.0 )
01253                                 break;
01254                 }
01255                 rand2 = (double)rand()/(double)RAND_MAX;
01256                 x = sqrt ( -2.0 * log ( rand1 ) ) * cos ( 2.0 * PI * rand2 );
01257                 y = sqrt ( -2.0 * log ( rand1 ) ) * sin ( 2.0 * PI * rand2 );
01258         }
01259         //  Otherwise, return the second, saved, value.
01260         else{
01261                 x = y;
01262         }
01263         ++used;
01264         return x;
01265 }
01266 
01267 
01268 /*! Applies noise to the given weight, returning a number between -128 and 127
01269         First get the random or normally distributed noise within the noise range
01270         Then convert to a number between -128 and 127. */
01271 short ConnectionManager::getWeight(double weight, double range, double normDist){
01272         if(normDist == 1){//Produce normally distributed noise around weight within range
01273                 /*Standard deviation is 1 with this implementation
01274                         95.45% of numbers are within two standard deviations
01275                         99% of the numbers are within three standard deviations - i.e. less than 3.0
01276                         So for the moment take three standard deviations either side, round off any numbers that exceed this
01277                         and compress the numbers within the noise range
01278                 */
01279                 //First sort out random number
01280                 double normRan = getNormalRandom();
01281                 if(normRan < -3.0)
01282                         normRan =-3.0;
01283                 else if(normRan > 3.0)
01284                         normRan = 3.0;
01285                 normRan = normRan * (range / 3.0);//Normally distributed numbers will vary between -3 and +3 so need to make them fit into the range
01286                 weight += normRan;//Add noise to weight
01287 
01288                 #ifdef WEIGHT_DEBUG
01289                         cout<<"Normally distributed noise: "<<normRan<<"; Weight: "<<weight;
01290                 #endif //WEIGHT_DEBUG
01291         }
01292         else{//Produce random noise around weight within range
01293                 int randomNum = rand();
01294                 double randomNoiseDoub = (double)randomNum *(range / (double)RAND_MAX);
01295                 weight += randomNoiseDoub; //Add noise to weight
01296 
01297                 #ifdef WEIGHT_DEBUG
01298                         cout<<"Random noise: "<<randomNoiseDoub<<"; Weight: "<<weight;
01299                 #endif //WEIGHT_DEBUG
01300         }
01301         //Check that it is in bounds and correct if not
01302         if(weight > 1.0)
01303                 weight = 1.0;
01304         else if (weight < -1.0)
01305                 weight = -1.0;
01306                         
01307         //Finally convert weight to range -128 - 127
01308         int finalWeight = (int)rint(weight * 127);
01309 
01310         #ifdef WEIGHT_DEBUG
01311                 cout<<"; Final weight: "<<finalWeight<<"; Range "<<range<<endl;
01312         #endif //WEIGHT_DEBUG
01313 
01314         return finalWeight;
01315 }
01316 
01317 
01318 /*! Returns true if the neuron is an excitatory neuron, either because it already has just excitatory connections
01319         or a random number is used to select its type. */
01320 bool ConnectionManager::isExcitatoryNeuron(unsigned int neuronID, double excitatoryPercentage){
01321         //Count up the number of excitatory connections that this neuron makes
01322         Query query = networkDBInterface->getQuery();
01323         query.reset();
01324         query<<"SELECT COUNT(*) FROM Connections WHERE PreSynapticNeuronID = "<<neuronID<<" AND Weight > 0";
01325         Result exciteRes = query.store();
01326         Row exciteRow(*exciteRes.begin());//Should be only one row
01327         unsigned int numExcitatoryConns = Utilities::getUInt((std::string)exciteRow["COUNT(*)"]);
01328 
01329         //Count up the number of inhibitory connections that this neuron makes
01330         query.reset();
01331         query<<"SELECT COUNT(*) FROM Connections WHERE PreSynapticNeuronID = "<<neuronID<<" AND Weight < 0";
01332         Result inhibRes = query.store();
01333         Row inhibRow(*inhibRes.begin());//Should be only one row
01334         unsigned int numInhibitoryConns = Utilities::getUInt((std::string)inhibRow["COUNT(*)"]);
01335 
01336         if(numExcitatoryConns > 0 && numInhibitoryConns == 0){//Already just has excitatory connections
01337                 return true;
01338         }
01339         else if(numExcitatoryConns == 0 && numInhibitoryConns > 0){//Already just has inhibitory connections
01340                 return false;
01341         }
01342         else if(numExcitatoryConns > 0 && numInhibitoryConns > 0){//Mixed excitatory and inhibitory should not be processed by this method.
01343                 cerr<<"ConnectionManager: Error creating Unstructured excitatory/ inhibitory connections. Neuron "<<neuronID<<" has both excitatory and inhibitory connections."<<endl;
01344                 throw createConnectionException;
01345         }
01346 
01347         //If we have reached this point neuron has no connections, so choose its type at random.
01348         int threshold = (int)rint( (excitatoryPercentage / 100.0) * (double)RAND_MAX);
01349         if(rand() < threshold)
01350                 return true;
01351         return false;
01352 }
01353 
01354 
01355 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4