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

PatternManager.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 "PatternManager.h"
00025 #include "Debug.h"
00026 #include "Utilities.h"
00027 #include "PatternTypes.h"
00028 #include "SpikeStreamSimulation.h"
00029 
00030 //Other includes
00031 #include <iostream>
00032 #include <mysql++.h>
00033 using namespace mysqlpp;
00034 using namespace std;
00035 
00036 
00037 /*! Constructor. */
00038 PatternManager::PatternManager(DBInterface *netDBInter, DBInterface *pattDBInter, unsigned int neurGrpID, unsigned int pattGrpID){
00039         //Store references
00040         networkDBInterface = netDBInter;
00041         patternDBInterface = pattDBInter;
00042 
00043         //Store id of neuron group that this task is simulating
00044         neuronGrpID = neurGrpID;
00045 
00046         //Initialise variables
00047         bufferCounter = 0;
00048         patternLoaded = false;
00049         rotatePattern = false;
00050         patternGrpID = 0;
00051 
00052         //Create a new connection to the pattern dbInterface
00053         try{
00054                 patternConnection = patternDBInterface->getNewConnection();
00055                 if(!patternConnection){
00056                         SpikeStreamSimulation::systemError("PatternManager: NEW CONNECTION TO DATABASE FAILED");
00057                         return;
00058                 }
00059                 patternQuery = new Query(patternConnection->query());
00060         }
00061         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00062                 ostringstream errorStrStream;
00063                 errorStrStream<<"Exception thrown getting pattern query: \""<<er.what()<<"\"";
00064                 SpikeStreamSimulation::systemError(errorStrStream.str());
00065                 return;
00066         }
00067 
00068         //Load up pattern
00069         loadPatternGroup(pattGrpID);
00070 }
00071 
00072 
00073 /*! Destructor. */
00074 PatternManager::~ PatternManager(){
00075         #ifdef MEMORY_DEBUG
00076                 cout<<"DESTROYING PATTERN MANAGER"<<endl;
00077         #endif//MEMORY_DEBUG
00078 
00079         if(patternLoaded){
00080                 unloadPatternGroup();
00081         }
00082 
00083         //Delete the query that we have created on the heap
00084         delete patternQuery;
00085 
00086         //Close the connection used by this class
00087         patternConnection->close();
00088 }
00089 
00090 
00091 //-------------------------------------------------------------------------
00092 //-------------------------- PUBLIC METHODS -------------------------------
00093 //-------------------------------------------------------------------------
00094 
00095 /*! Fires neurons in the neuron array according to the pattern. */
00096 void PatternManager::fireNeurons(){
00097         //Make sure that pattern is loaded
00098         if(!patternLoaded)
00099                 return;
00100         
00101         //Fire all the neurons at the current position in the buffer
00102         for(vector<unsigned int>::iterator iter = patternBuffer[bufferCounter].begin(); iter != patternBuffer[bufferCounter].end(); ++iter){
00103                 neuronArray[*iter]->fireNeuron();
00104         }
00105 
00106         //Advance buffer counter if appropriate
00107         if(patternType == TEMPORAL_PATTERN_VALUE){
00108                 patternBuffer[bufferCounter].clear();//Empty the buffer's vector
00109                 ++bufferCounter;
00110                 bufferCounter = bufferCounter % NUMBER_OF_DELAY_VALUES;
00111         }
00112 }
00113 
00114 
00115 /*! Loads pattern data from the database into the pattern buffer.
00116         This data will change the firing pattern when fireNeurons()
00117         is called. */
00118 // FIXME NEED TO HANDLE ROTATION OF PATTERNS
00119 void PatternManager::loadPatternData(){
00120         /* Double check that pattern has been successfully loaded
00121                 Not necessarily an error if there is no pattern loaded since it
00122                 may have finished and this method is still being called by neuron simulation */
00123         if(!patternLoaded){
00124                 return;
00125         }
00126 
00127         /* Static patterns always insert at zero - delayValue = 0
00128                 so need to empty buffer at this position */
00129         if(patternType == STATIC_PATTERN_VALUE)
00130                 patternBuffer[0].clear();
00131                 
00132         //Load pattern
00133         try{
00134                 Row patternRow = patternResults->fetch_row();
00135                 string patternDataString = (std::string) patternRow["Pattern"];
00136                 fillPatternArray(patternDataString);
00137                 
00138                 /* Neuron groups are loaded horizontally from bottonm to top. Patterns are loaded
00139                         horizontally from top to bottom. So need a bit of fiddling to map one to the other
00140                         Need to handle rotation of the pattern wrt the neuron group*/
00141                 if(rotatePattern == false){
00142                         for(unsigned int i=0; i<neuronGrpLength; ++i){
00143                                 for(unsigned int j=0; j < neuronGrpWidth; ++j){
00144                                         int neuronArrayIndex = j + i*neuronGrpWidth;//Location in the neuron array
00145                                         int patternArrayIndex = j + (neuronGrpLength - i - 1) * neuronGrpWidth;//location in the pattern array
00146 
00147                                         //In a static pattern, the value should be 1 or 0
00148                                         if(patternType == STATIC_PATTERN_VALUE){
00149                                                 if(patternArray[patternArrayIndex] == 1){
00150                                                         patternBuffer[0].push_back(neuronArrayIndex);
00151                                                 }
00152                                         }
00153                                         //Pattern value is the amount of delay
00154                                         else{
00155                                                 if(patternArray[patternArrayIndex] > -1){//Neuron fires, so add to patternBuffer
00156                                                         int insertionPosition = (bufferCounter + patternArray[patternArrayIndex] ) % NUMBER_OF_DELAY_VALUES;
00157                                                         patternBuffer[insertionPosition].push_back(neuronArrayIndex);
00158                                                 }
00159                                         }
00160                                 }
00161                         }
00162                 }
00163                 else{
00164                         SpikeStreamSimulation::systemError("PATTERN ROTATION NOT IMPLEMENTED YET.");
00165                 }
00166 
00167                 #ifdef PATTERN_DEBUG
00168                         cout<<"Pattern data loaded"<<endl;
00169                 #endif//PATTERN_DEBUG
00170                 
00171         }
00172         catch (const EndOfResults& er) {//EndOfResults exception thrown when fetch row no longer returns anything
00173                 //No more rows to fetch, so unload pattern
00174                 cout<<"PatternManager: End of pattern. Stopping"<<endl;
00175                 unloadPatternGroup();
00176         }
00177         catch (const BadQuery& er) {// Handle any query errors
00178                 ostringstream errorStrStream;
00179                 errorStrStream<<"Bad query when loading pattern data: \""<<er.what()<<"\"";
00180                 SpikeStreamSimulation::systemError(errorStrStream.str());
00181         }
00182         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00183                 ostringstream errorStrStream;
00184                 errorStrStream<<"Exception thrown loading pattern data: \""<<er.what()<<"\"";
00185                 SpikeStreamSimulation::systemError(errorStrStream.str());
00186         }
00187         catch(std::exception& er){// Catch-all for any other exceptions
00188                 ostringstream errorStrStream;
00189                 errorStrStream<<"Exception thrown loading pattern data: \""<<er.what()<<"\"";
00190                 SpikeStreamSimulation::systemError(errorStrStream.str());
00191         }
00192 }
00193 
00194 
00195 /*! Passes a reference to the array of neurons held in SpikeStreamSimulation. */
00196 void PatternManager::setNeuronArray(Neuron **neurArr, int neurArrLen){
00197         neuronArray = neurArr;
00198         numberOfNeurons = neurArrLen;
00199 }
00200 
00201 
00202 //-------------------------------------------------------------------------
00203 //--------------------------- PRIVATE METHODS -----------------------------
00204 //-------------------------------------------------------------------------
00205 
00206 /*! Loads the supplied patternArray with the values from the patternString.
00207         These are separated with commas. */
00208 void PatternManager::fillPatternArray(string &patternString){
00209         int patternCounter = 0;
00210         string tempString = "";
00211         for(unsigned int stringCounter = 0; stringCounter < patternString.length(); ++stringCounter){
00212                 if((patternString[stringCounter] == '-') || isdigit(patternString[stringCounter])){//Have found a number
00213                         
00214                         //Keep loading number until I reach ',' or ' '
00215                         while(((patternString[stringCounter] == '-') || isdigit(patternString[stringCounter])) && stringCounter != patternString.length()){
00216                                 tempString += patternString[stringCounter];
00217                                 ++stringCounter;
00218                         }
00219                         //Breaks out of while loop when char is not part of a number or at the end of the string
00220                         
00221                         //Convert the number to an integer and add to pattern array
00222                         if(patternCounter >= patternArrayLength){//Will exceed pattern array length
00223                                 ostringstream errorStrStream;
00224                                 errorStrStream<<"PatternManager: ERROR FILLING PATTERN ARRAY: TOO MANY NUMBERS "<<"PatternCounter = "<<patternCounter<<" length = "<<patternArrayLength<<endl;
00225                                 SpikeStreamSimulation::systemError(errorStrStream.str());
00226                                 break;
00227                         }
00228 
00229                         try{
00230                                 patternArray[patternCounter] = Utilities::getInt(tempString);
00231                         }
00232                         catch(std::exception& er){// Catch exceptions thrown converting the string to an integer
00233                                 ostringstream errorStrStream;
00234                                 errorStrStream<<"Exception thrown extracting integer from pattern array: \""<<er.what()<<"\"";
00235                                 SpikeStreamSimulation::systemError(errorStrStream.str());
00236                                 break;
00237                         }
00238                         ++patternCounter;
00239                         tempString = "";
00240                 }
00241                 //Otherwise character is not part of a number so continue with for loop
00242         }
00243 
00244         /*Check that correct number of integers have been loaded. 
00245                 Should have exited from the for loop with after filling the array and
00246                 incrementing the pattern counter one more time */
00247         if(patternCounter != patternArrayLength){//Have not loaded enough into array
00248                 ostringstream errorStrStream;
00249                 errorStrStream<<"PatternManager: ERROR FILLING PATTERN ARRAY: PROBABLY TOO FEW NUMBERS "<<"PatternCounter = "<<patternCounter<<" length = "<<patternArrayLength<<endl;
00250                 SpikeStreamSimulation::systemError(errorStrStream.str());
00251         }
00252 
00253         #ifdef PATTERN_DEBUG
00254                 cout<<"==================================== START PATTERN ARRAY ==============================="<<endl;
00255                 for(int i=0; i<patternArrayLength; ++i)
00256                         cout<<"Pattern array: "<<i<<"   "<<patternArray[i]<<endl;
00257                 cout<<"===================================== END PATTERN ARRAY ==============================="<<endl;
00258         #endif//PATTERN_DEBUG
00259 }
00260 
00261 
00262 /*! Loads up a set of patterns from the database ready to be played back
00263         as the simulation progresses. */
00264 void PatternManager::loadPatternGroup(unsigned int pattGrpID){
00265         //Store the current pattern group id
00266         patternGrpID = pattGrpID;
00267 
00268         //Do any steps necessary to clean up previous archive
00269         if(patternLoaded){
00270                 unloadPatternGroup();
00271         }
00272 
00273         /* Get the width and length of the neuron group to see if they match and if
00274                 the pattern needs to be rotated */
00275 
00276         //Get information about neuron group
00277         try{
00278                 Query networkQuery = networkDBInterface->getQuery();
00279                 networkQuery.reset();
00280                 networkQuery<<"SELECT Width, Length FROM NeuronGroups WHERE NeuronGrpID = "<<neuronGrpID;
00281                 Result networkResults = networkQuery.store();
00282                 Row networkRow(*networkResults.begin());
00283                 neuronGrpWidth = Utilities::getUInt((std::string)networkRow["Width"]);
00284                 neuronGrpLength = Utilities::getUInt((std::string)networkRow["Length"]);
00285         
00286                 //Get information about pattern 
00287                 Query tempPattQuery = patternDBInterface->getQuery();
00288                 tempPattQuery.reset();
00289                 tempPattQuery<<"SELECT Width, Length, PatternType FROM PatternDescriptions WHERE PatternGrpID = "<<patternGrpID;
00290                 Result tempPattResults = tempPattQuery.store();
00291                 Row tempPattRow(*tempPattResults.begin());
00292                 patternType = Utilities::getUInt((std::string)tempPattRow["PatternType"]);
00293                 unsigned int patternWidth = Utilities::getUInt((std::string)tempPattRow["Width"]);
00294                 unsigned int patternLength = Utilities::getUInt((std::string)tempPattRow["Length"]);
00295         
00296                 //Sort out the rotation of the pattern
00297                         //FIXME ROTATION IS NOT IMPLEMENTED YET
00298                 if(neuronGrpWidth == patternWidth && neuronGrpLength == patternLength){
00299                         rotatePattern = false;
00300                 } 
00301                 else if(neuronGrpWidth == patternLength && neuronGrpLength == patternWidth){
00302                         rotatePattern = true;
00303                         SpikeStreamSimulation::systemError("PatternManager: ROTATION NOT IMPLEMENTED\nPATTERN DOES NOT MATCH NEURON GROUP WIDTH AND LENGTH.");
00304                         return;
00305                 }
00306                 else{
00307                         SpikeStreamSimulation::systemError("PatternManager: PATTERN DOES NOT MATCH NEURON GROUP WIDTH AND LENGTH");
00308                         return;
00309                 }
00310         
00311                 //Set up the pattern array that will be used to hold the unpacked pattern data
00312                 patternArrayLength = patternWidth * patternLength;
00313                 patternArray = new int[patternArrayLength];
00314         
00315                 //Set up the query and the results that will be used to stream from database
00316                 patternQuery->reset();
00317                 (*patternQuery)<<"SELECT PatternID, Pattern FROM PatternData WHERE PatternGrpID = "<<patternGrpID<<" ORDER BY PatternID";
00318                 patternResults = new ResUse(patternQuery->use());//Store pattern results
00319 
00320         }
00321         catch (const BadQuery& er) {// Handle any query errors
00322                 ostringstream errorStrStream;
00323                 errorStrStream<<"Bad query when loading pattern group: \""<<er.what()<<"\"";
00324                 SpikeStreamSimulation::systemError(errorStrStream.str());
00325                 return;
00326         }
00327         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00328                 ostringstream errorStrStream;
00329                 errorStrStream<<"Exception thrown loading pattern group: \""<<er.what()<<"\"";
00330                 SpikeStreamSimulation::systemError(errorStrStream.str());
00331                 return;
00332         }
00333         catch(std::exception& er){// Catch-all for any other exceptions
00334                 ostringstream errorStrStream;
00335                 errorStrStream<<"Exception thrown loading pattern group: \""<<er.what()<<"\"";
00336                 SpikeStreamSimulation::systemError(errorStrStream.str());
00337                 return;
00338         }
00339 
00340 
00341         //Check to see that results are ok
00342         if(!(*patternResults)){
00343                 SpikeStreamSimulation::systemError("PatternManager: SQL ERROR");
00344                 return;
00345         }
00346 
00347         #ifdef PATTERN_DEBUG
00348                 cout<<"Pattern description loaded."<<endl;
00349         #endif//PATTERN_DEBUG
00350 
00351         //Everything ok up to this point
00352         patternLoaded = true;
00353 
00354         //Load the first pattern
00355         loadPatternData();
00356 }
00357 
00358 
00359 /*! Unloads the pattern. */
00360 void PatternManager::unloadPatternGroup(){
00361         delete patternResults;
00362         patternGrpID = 0;
00363         patternLoaded = false;
00364 
00365         //Reset all buffers
00366         for(int i=0; i<NUMBER_OF_DELAY_VALUES; ++i)
00367                 patternBuffer[i].clear();
00368 
00369         //Free memory from pattern array
00370         delete [] patternArray;
00371 }
00372 
00373 

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