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
1.4.4