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

Neuron.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Simulation                                                *
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 "Neuron.h"
00025 #include "Debug.h"
00026 
00027 //Other includes
00028 #include <iostream>
00029 using namespace std;
00030 
00031 
00032 /*! Constructor. */
00033 Neuron::Neuron(){
00034         /* Make neuron fire time large and negative so that at start up it appears as if the
00035                 neuron fired in the distant past */
00036         neuronFireTime = -100.0;
00037         neuronFireCount = 0;
00038 
00039         //Initialise monitoring data
00040         monitorData.dataArray = NULL;
00041         monitorData.length = 0;
00042 }
00043 
00044 
00045 /*! Destructor. */
00046 Neuron::~Neuron(){
00047         #ifdef MEMORY_DEBUG
00048                 cout<<"DELETING NEURON."<<endl;
00049         #endif//MEMORY_DEBUG    
00050 
00051         delete [] connectionArray;
00052         delete [] spikeTaskHolderArray;
00053 
00054         //Connection holders do not need deleting since they are currently on the stack
00055 }
00056 
00057 
00058 //-----------------------------------------------------------------------------------
00059 //------------------------------ PUBLIC METHODS -------------------------------------
00060 //-----------------------------------------------------------------------------------
00061 
00062 /*! This function fires the neuron and adds a reference to the list of synapse ids 
00063         that it connects to to the appropriate task holder. These task ids are then copied 
00064         directly into the message buffer when the spike lists are sent. */
00065 void Neuron::fireNeuron(){
00066         neuronFireTime = simulationClock->getSimulationTime();
00067         ++neuronFireCount;
00068 
00069         #ifdef FIRE_NEURON_DEBUG
00070                 cout<<"Firing neuron "<<neuronID<<" at simulationTime "<<neuronFireTime<<" with neuronFireCount = "<<neuronFireCount<<endl;
00071         #endif //FIRE_NEURON_DEBUG
00072 
00073         /* Work through the list of connections
00074                 Need to store the reference to the array and the array size in the appropriate
00075                 place in the spike task holder */
00076         for(unsigned int i=0; i<numberOfSpikeTaskHolders; ++i){
00077 
00078                 //Get pointer to the array containing all the connections for this task holder
00079                 destTID = spikeTaskHolderArray[i]->primaryDestinationID;
00080                 
00081                 /* Work through the vector of connection holders for the task */
00082                 for(vector<ConnectionHolder>::iterator iter = connectionMap[destTID].begin(); iter != connectionMap[destTID].end(); ++iter){
00083 
00084                         /* Get the point in time at which I want to insert the connection holder. 
00085                                 The delay of the connection holder has to be added to the time counter, which
00086                                 cycles through 0 - NUMBER_OF_DELAY_VALUES */
00087                         bufferInsertionPoint = (spikeTaskHolderArray[i]->bufferCounter + iter->delay) % NUMBER_OF_DELAY_VALUES;
00088 
00089                         /* NOTE noise in the delay could be added here. It is essential that this does not
00090                                 lead to spikes overtaking each other or arriving at the same time, which would
00091                                 not be biologically realistic. So only want to alter delay by a few percent at most */
00092                         
00093                         /* This line performs the following:
00094                                 Get the task holder at taskHolderArray[i]
00095                                 In the array of buffers held as vectors, 1 for each time point,
00096                                 Add a reference to a connectionHolder, containing a list of connectionIDs for this point */
00097                         spikeTaskHolderArray[i]->spikeMessageBuffer[bufferInsertionPoint].push_back(&(*iter));
00098                         
00099                         //Increase the count of the number of spikes in the message
00100                         spikeTaskHolderArray[i]->messageSpikeCount[bufferInsertionPoint] += iter->numConnIDs;
00101                 }
00102         }
00103 
00104         //Add the neuron ID to the neuronTaskHolder
00105         neuronTaskHolder->firingNeuronVector.push_back(neuronID);       
00106 }
00107 
00108 
00109 /* Returns a MonitorData structure containing a pointer to an array containing the current values 
00110         of the monitored data items in the same order as they were listed in the XML file. This data
00111         structure also contains the length of the array. */
00112 MonitorData* Neuron::getMonitoringData(){
00113         return &monitorData;
00114 }
00115 
00116 /* Returns a string containing the data that is output by this neuron in monitoring mode in XML format.
00117         The implementation in Neuron does not contain any monitored parameters. Overload this method if you 
00118         want to send actual information back. */ 
00119 string Neuron::getMonitoringInfo(){
00120         string xmlString = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
00121         xmlString += "<monitor_info>";
00122         xmlString += "</monitor_info>";
00123         return xmlString;
00124 }
00125 
00126 
00127 /*! Returns the number of times the neuron has fired since the beginning
00128         of the simulation. */
00129 int Neuron::getNeuronFireCount(){
00130         return neuronFireCount;
00131 }
00132 
00133 
00134 /*! Accesses the neuronID of this neuron. */
00135 unsigned int Neuron::getNeuronID(){
00136         return neuronID;
00137 }
00138 
00139 
00140 //------------------------------------------------------------------------------
00141 //---------------------------- PRIVATE METHODS ---------------------------------
00142 //------------------------------------------------------------------------------
00143 
00144 /*! Prints all of the connections. */
00145 void Neuron::printConnections(){
00146         cout<<"===================================== START NEURON ============================================="<<endl;
00147         cout<<"Neuron ID: "<<neuronID<<"; Number of task holders: "<<numberOfSpikeTaskHolders<<endl;
00148 
00149         //Work through each task holder
00150         for(map<int, vector<ConnectionHolder> >::iterator taskIter = connectionMap.begin(); taskIter != connectionMap.end(); ++taskIter){
00151                 cout<<"     TaskID: "<<taskIter->first<<endl;
00152 
00153                 //Work through each of the connectionHolders held within the task holder
00154                 for(vector<ConnectionHolder>::iterator connHoldIter = taskIter->second.begin(); connHoldIter != taskIter->second.end(); ++connHoldIter){
00155                         cout<<"          Delay: "<<connHoldIter->delay<<"; Size: "<<connHoldIter->numConnIDs<<endl;
00156 
00157                         /* Output the from and to neuronIDs in the connectionHolder. 
00158                                 There are two numbers for each ID so need to advance i by 2 each time */
00159                         for(int i=0; i<connHoldIter->numConnIDs; i += 2)
00160                                 cout<<"               FromNeuron: "<<connHoldIter->connIDArray[i]<<"; ToNeuron: "<<connHoldIter->connIDArray[i+1]<<endl;
00161                 }
00162         }
00163         cout<<"ConnectionArray ( Number of connections = "<<numberOfConnections<<" ): ";
00164         for(unsigned int i=0; i< numberOfConnections; ++i)
00165                 cout<<" "<<connectionArray[i];
00166         cout<<endl;
00167         cout<<"======================================== END NEURON ============================================"<<endl;
00168 }
00169 
00170 
00171 /*! Sets the neuron ID. This cannot be done in the constructor since an 
00172         array of neurons is created all at once using empty constructors when 
00173         the neuron array is declared. */
00174 void Neuron::setNeuronID(unsigned int neurID){
00175         neuronID = neurID;
00176 }
00177 
00178 
00179 /*! Store reference to simulation clock. */
00180 /* FIXME THIS WOULD BE BETTER STATIC, BUT HAVE HAD PROBLEMS WITH THIS CONNECTED
00181         EITHER WITH INHERITANCE OF STATIC VARIABLES, LOADING OF DYNAMIC LIBRARIES OR 
00182         PERHAPS BOTH! */
00183 void Neuron::setSimulationClock(SimulationClock* simClock){
00184         simulationClock = simClock;
00185 }
00186 
00187 
00188 /*! Passes a pointer to the synapse map
00189         Note that this is of type: dense_hash_map<unsigned int, dense_hash_map<unsigned int, Synapse*, hash<unsigned int> >*, hash<unsigned int> >
00190         I.E. it is a dense_hash_map containing pointers to further dense hash maps
00191         See the SpikeStreamSimulation code for examples of iterating through and accessing this map. */
00192 void Neuron::setSynapseMapPtr(void* synMapPtr){
00193         synapseMapPtr = synMapPtr;
00194 }
00195 
00196 

Generated on Mon Sep 3 22:24:34 2007 for SpikeStream Simulation by  doxygen 1.4.4