From 0ff1b77a6fa7152903e2a3f8e0fbe658fb314e5c Mon Sep 17 00:00:00 2001 From: Dilawar Singh <dilawars@ncbs.res.in> Date: Fri, 21 Apr 2017 17:18:43 +0530 Subject: [PATCH] Squashed 'moose-core/' changes from 270c880..eb878dd eb878dd Merge branch 'master' of https://github.com/BhallaLab/moose-core 68ef2ed Less verbose ReadSwc and rdesigneur. Fix to SeqSynHandler 2c93c52 return type from None to moose.shell 07fc0f9 Ignore /opt/bin/python3 on travis. Numpy is not available for this path. Try /usr/bin/python3. 45fb960 mtseed and mtrand are under moose namespace and defined in global.h file. Fixes for travis failure with BOOST. dfa0ab1 Explicitly naming the source file in synapse directory. cd32764 old makefile based flow is deprecated. Recent commit fixed the test faillure. c0f5469 Merge branch 'master' of https://github.com/BhallaLab/moose-core fd96222 Verbose flag for rdesigneur; added synapseOrder to SeqSynHandler, fixes to testSynapse e7d57cf plot_tables can plot on user given axis. 43faa23 mu.plot_records is renamed to mu.plot_tables. 99f5ee7 Merge branch 'master' of github.com:BhallaLab/moose-core 953142d Fixed for snappy builds. 6931e80 Let cmake find path of Python.h file. 8e4291a Merge commit '4489d15994d2ab9ab2448afd937ba13c65a9907d' 9513005 More changes to snap. Needs to add Python.h path [skip ci] a2a67bc Removed <<<<, === and >>> from improper merge. 1cd99cb Added snapcraft file. 2975d3f Fixes to plotTables utility function. git-subtree-dir: moose-core git-subtree-split: eb878ddb88f7d69fca0e0858bf9332ff0661e6d8 --- .travis/travis_build_linux.sh | 10 +-- VERSION | 1 - basecode/global.cpp | 2 +- basecode/global.h | 2 +- biophysics/ReadSwc.cpp | 10 +-- pymoose/CMakeLists.txt | 22 ++++-- python/moose/SBML/readSBML.py | 5 +- python/moose/plot_utils.py | 44 +++++++----- python/rdesigneur/rdesigneur.py | 9 ++- synapse/CMakeLists.txt | 15 +++- synapse/RollingMatrix.cpp | 2 +- synapse/SeqSynHandler.cpp | 122 ++++++++++++++++++++++++++++++-- synapse/SeqSynHandler.h | 25 ++++++- synapse/testSynapse.cpp | 71 +++++++++++-------- 14 files changed, 262 insertions(+), 78 deletions(-) delete mode 100644 VERSION diff --git a/.travis/travis_build_linux.sh b/.travis/travis_build_linux.sh index 5530f9a7..3a2ebbfa 100755 --- a/.travis/travis_build_linux.sh +++ b/.travis/travis_build_linux.sh @@ -20,20 +20,22 @@ set -o nounset # Treat unset variables as an error set -e -PYTHON2="/usr/bin/python2" -PYTHON3=`which python3` #MAKEFLAGS="-j 4" +PYTHON2="/usr/bin/python2" # Bug: `which python` returns /opt/bin/python* etc on travis. For which numpy # many not be available. Therefore, it is neccessary to use fixed path for # python executable. +PYTHON3="/usr/bin/python3" ( # Old makefile based flow. $PYTHON2 -m compileall -q . if type $PYTHON3 > /dev/null; then $PYTHON3 -m compileall -q . ; fi - # Traditional make. - make + ## DEPRECATED: No longer testing make file. + + ## Traditional make. + #make ## CMAKE based flow mkdir -p _GSL_BUILD && cd _GSL_BUILD && \ cmake -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON2" .. diff --git a/VERSION b/VERSION deleted file mode 100644 index 93738075..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -3.1.1-129-g669b981 \ No newline at end of file diff --git a/basecode/global.cpp b/basecode/global.cpp index ec5a523e..b54fc979 100644 --- a/basecode/global.cpp +++ b/basecode/global.cpp @@ -87,7 +87,7 @@ namespace moose { * * @param x */ - void mtseed( unsigned int x ) + void mtseed( int x ) { moose::__rng_seed__ = x; moose::rng.setSeed( x ); diff --git a/basecode/global.h b/basecode/global.h index 9b06b282..40b2dba5 100644 --- a/basecode/global.h +++ b/basecode/global.h @@ -109,7 +109,7 @@ namespace moose * * @param seed */ - void mtseed( unsigned int seed ); + void mtseed( int seed ); /** * @brief Generate a random double between 0 and 1 diff --git a/biophysics/ReadSwc.cpp b/biophysics/ReadSwc.cpp index 9894e047..3fde18ec 100644 --- a/biophysics/ReadSwc.cpp +++ b/biophysics/ReadSwc.cpp @@ -23,6 +23,7 @@ static const double MinRadius = 0.04; ReadSwc::ReadSwc( const string& fname ) { + bool verbose = false; ifstream fin( fname.c_str() ); if ( !fin ) { cerr << "ReadSwc:: could not open file " << fname << endl; @@ -52,12 +53,13 @@ ReadSwc::ReadSwc( const string& fname ) cleanZeroLength(); parseBranches(); } - cout << "ReadSwc: " << fname << " : NumSegs = " << segs_.size() << + cout << "ReadSwc: " << fname << " : " << (valid ? "OK" : "FAILED" )<< + ", # Branches = " << branches_.size() << + ". # Segs = " << segs_.size() << ", bad = " << badSegs << - ", Validated = " << valid << - ", numBranches = " << branches_.size() << endl; - diagnostics(); + if ( verbose ) + diagnostics(); } bool ReadSwc::validate() const diff --git a/pymoose/CMakeLists.txt b/pymoose/CMakeLists.txt index 83397de4..af4e8e74 100644 --- a/pymoose/CMakeLists.txt +++ b/pymoose/CMakeLists.txt @@ -1,6 +1,8 @@ add_definitions(-DPYMOOSE) include_directories(../basecode ../msg) +find_package( PythonInterp REQUIRED ) + set(PYMOOSE_SRCS moosemodule.cpp vec.cpp @@ -18,10 +20,18 @@ EXEC_PROGRAM(${PYTHON_EXECUTABLE} except Exception: pass'" OUTPUT_VARIABLE PYTHON_SO_EXTENSION ) + +message( STATUS "Python path ${PYTHON_EXECUTABLE}" ) message( STATUS "Python so extension ${PYTHON_SO_EXTENSION}" ) find_package(NumPy REQUIRED) -include_directories(${NUMPY_INCLUDE_DIRS}) +find_package(PythonLibs REQUIRED) + +include_directories( ${NUMPY_INCLUDE_DIRS} ) +include_directories( ${PYTHON_INCLUDE_DIRS} ) + +message( STATUS "Python include dir : ${PYTHON_INCLUDE_DIRS} " ) + add_definitions(-DUSE_NUMPY) add_definitions(-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION) @@ -34,7 +44,12 @@ execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --libs OUTPUT_VARIABLE PYTHON_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE ) + +if( NOT PYTHON_INCLUDE_FLAGS ) + set( PYTHON_INCLUDE_FLAGS "-I ${PYTHON_INCLUDE_DIRS} " ) +endif( ) message( STATUS "Python include flags: ${PYTHON_INCLUDE_FLAGS}" ) + set_target_properties(_moose PROPERTIES COMPILE_DEFINITIONS "PYMOOSE" COMPILE_FLAGS "${PYTHON_INCLUDE_FLAGS}" @@ -43,11 +58,6 @@ set_target_properties(_moose PROPERTIES SUFFIX ".so" ) -#if(NOT(PYTHON_SO_EXTENSION STREQUAL "")) -# set_target_properties(_moose PROPERTIES -# SUFFIX ${PYTHON_SO_EXTENSION}) -#endif() - # see issue #80 if(HDF5_LIBRARY_DIRS) set_target_properties( _moose PROPERTIES LINK_FLAGS "-L${HDF5_LIBRARY_DIRS}" ) diff --git a/python/moose/SBML/readSBML.py b/python/moose/SBML/readSBML.py index 22044297..255d9678 100644 --- a/python/moose/SBML/readSBML.py +++ b/python/moose/SBML/readSBML.py @@ -66,11 +66,12 @@ def mooseReadSBML(filepath, loadpath, solver="ee"): '\n\t easy_install python-libsbml' '\n\t apt-get install python-libsbml' ) - return None + return moose.element('/') if not os.path.isfile(filepath): print('%s is not found ' % filepath) - return None + return moose.element('/') + with open(filepath, "r") as filep: filep = open(filepath, "r") diff --git a/python/moose/plot_utils.py b/python/moose/plot_utils.py index b2740954..94c8577e 100644 --- a/python/moose/plot_utils.py +++ b/python/moose/plot_utils.py @@ -135,7 +135,7 @@ def plotTables(tables, outfile=None, **kwargs): subplot = kwargs.get('subplot', True) for i, tname in enumerate(tables): if subplot: - plt.subplot(len(tables), 1, i) + plt.subplot(len(tables), 1, i+1) yvec = tables[tname].vector xvec = np.linspace(0, moose.Clock('/clock').currentTime, len(yvec)) plt.plot(xvec, yvec, label=tname) @@ -165,7 +165,7 @@ def plotVector(vec, xvec = None, **options): :param vec: Given vector. :param **kwargs: Optional to pass to maplotlib. """ - + ax = options[ 'ax' ] assert type(vec) == np.ndarray, "Expected type %s" % type(vec) legend = options.get('legend', True) @@ -176,28 +176,29 @@ def plotVector(vec, xvec = None, **options): xx = xvec[:] assert len(xx) == len(vec), "Expecting %s got %s" % (len(vec), len(xvec)) + ax.plot(xx, vec, label=options.get('label', '')) - plt.plot(xx, vec, label=options.get('label', '')) if legend: # This may not be available on older version of matplotlib. try: - plt.legend(loc='best', framealpha=0.4) + ax.legend(loc='best', framealpha=0.4) except: - plt.legend(loc='best') + ax.legend(loc='best') if xvec is None: - plt.xlabel('Time (sec)') + ax.set_xlabel('Time (sec)') else: - plt.xlabel(options.get('xlabel', '')) + ax.set_xlabel(options.get('xlabel', '')) - plt.ylabel = options.get('ylabel', '') - plt.title(options.get('title', '')) + ax.set_ylabel = options.get('ylabel', '') + ax.set_title(options.get('title', '')) if(options.get('legend', True)): try: - plt.legend(loc='best', framealpha=0.4, prop={'size' : 9}) + ax.legend(loc='best', framealpha=0.4, prop={'size' : 9}) except: - plt.legend(loc='best', prop={'size' : 9}) + ax.legend(loc='best', prop={'size' : 9}) + return ax def saveRecords(records, xvec = None, **kwargs): @@ -267,7 +268,7 @@ def plotRecords(records, xvec = None, **kwargs): yvec = dataDict[k].vector plotVector(yvec, xvec, label=k, **kwargs) else: - plt.subplot(len(dataDict), 1, i) + kwargs[ 'ax' ] = plt.subplot(len(dataDict), 1, i) yvec = dataDict[k].vector plotVector(yvec, xvec, label=k, **kwargs) @@ -286,9 +287,13 @@ def plotRecords(records, xvec = None, **kwargs): else: plt.show() +def plot_records( data_dict, xvec = None, **kwargs ): + """Renamed (deprecated) + """ + return plot_tables( data_dict, xvec, **kwargs ) -def plot_records(data_dict, xvec = None, **kwargs): - """plot_records Plot given dictionary. +def plot_tables(data_dict, xvec = None, **kwargs): + """plot_tables plots moose.Table stored in a dictionary. :param data_dict: :param xvec: If None, use moose.Clock to generate xvec. @@ -300,7 +305,12 @@ def plot_records(data_dict, xvec = None, **kwargs): subplot = kwargs.get('subplot', False) filters = [ x.lower() for x in kwargs.get('filter', [])] - plt.figure(figsize=(10, 1.5*len(data_dict))) + ax = kwargs.get( 'ax', None ) + if ax is None: + plt.figure(figsize=(10, 1.5*len(data_dict))) + if not subplot: + ax = plt.subplot( 1, 1, 1 ) + for i, k in enumerate(data_dict): pu.info("+ Plotting for %s" % k) plotThis = False @@ -312,10 +322,10 @@ def plot_records(data_dict, xvec = None, **kwargs): if plotThis: if not subplot: - yvec = data_dict[k] + yvec = data_dict[k].vector plotVector(yvec, xvec, label=k, **kwargs) else: - plt.subplot(len(data_dict), 1, i) + ax = plt.subplot(len(data_dict), 1, i) yvec = data_dict[k] plotVector(yvec, xvec, label=k, **kwargs) if subplot: diff --git a/python/rdesigneur/rdesigneur.py b/python/rdesigneur/rdesigneur.py index ed38fce9..632e7ead 100644 --- a/python/rdesigneur/rdesigneur.py +++ b/python/rdesigneur/rdesigneur.py @@ -80,6 +80,7 @@ class rdesigneur: useGssa = True, combineSegments = True, stealCellFromLibrary = False, + verbose = True, diffusionLength= 2e-6, meshLambda = -1.0, #This is a backward compatibility hack temperature = 32, @@ -111,6 +112,7 @@ class rdesigneur: self.useGssa = useGssa self.combineSegments = combineSegments self.stealCellFromLibrary = stealCellFromLibrary + self.verbose = verbose self.diffusionLength= diffusionLength if meshLambda > 0.0: print("Warning: meshLambda argument is deprecated. Please use 'diffusionLength' instead.\nFor now rdesigneur will accept this argument.") @@ -201,7 +203,8 @@ class rdesigneur: self._buildMoogli() self._buildStims() self._configureClocks() - self._printModelStats() + if self.verbose: + self._printModelStats() self._savePlots() except BuildError as msg: @@ -315,7 +318,8 @@ class rdesigneur: return True if moose.exists( '/library/' + protoVec[0] ): #moose.copy('/library/' + protoVec[0], '/library/', protoVec[1]) - print('renaming /library/' + protoVec[0] + ' to ' + protoVec[1]) + if self.verbose: + print('renaming /library/' + protoVec[0] + ' to ' + protoVec[1]) moose.element( '/library/' + protoVec[0]).name = protoVec[1] #moose.le( '/library' ) return True @@ -596,6 +600,7 @@ class rdesigneur: def _buildMoogli( self ): knownFields = { 'Vm':('CompartmentBase', 'getVm', 1000, 'Memb. Potential (mV)', -80.0, 40.0 ), + 'initVm':('CompartmentBase', 'getInitVm', 1000, 'Init. Memb. Potl (mV)', -80.0, 40.0 ), 'Im':('CompartmentBase', 'getIm', 1e9, 'Memb. current (nA)', -10.0, 10.0 ), 'inject':('CompartmentBase', 'getInject', 1e9, 'inject current (nA)', -10.0, 10.0 ), 'Gbar':('ChanBase', 'getGbar', 1e9, 'chan max conductance (nS)', 0.0, 1.0 ), diff --git a/synapse/CMakeLists.txt b/synapse/CMakeLists.txt index bb47b977..2b7d3622 100644 --- a/synapse/CMakeLists.txt +++ b/synapse/CMakeLists.txt @@ -1,5 +1,18 @@ cmake_minimum_required(VERSION 2.8) + include_directories( ../basecode ../utility ../kinetics) include_directories( ../external/muparser/include/ ) -file(GLOB SYNAPSE_SRCS *.cpp) + +set( SYNAPSE_SRCS + GraupnerBrunel2012CaPlasticitySynHandler.cpp + RollingMatrix.cpp + SeqSynHandler.cpp + SimpleSynHandler.cpp + STDPSynapse.cpp + STDPSynHandler.cpp + Synapse.cpp + SynHandlerBase.cpp + testSynapse.cpp + ) + add_library(synapse ${SYNAPSE_SRCS} ) diff --git a/synapse/RollingMatrix.cpp b/synapse/RollingMatrix.cpp index f4f5193f..01818a83 100644 --- a/synapse/RollingMatrix.cpp +++ b/synapse/RollingMatrix.cpp @@ -72,7 +72,7 @@ double RollingMatrix::dotProduct( const vector< double >& input, unsigned int index = (row + currentStartRow_) % nrows_; const SparseVector& sv = rows_[index]; unsigned int i2 = input.size()/2; - unsigned int istart = (startColumn <= i2) ? 0 : startColumn - i2; + unsigned int istart = (startColumn >= i2) ? 0 : i2-startColumn; unsigned int colstart = (startColumn <= i2) ? 0 : startColumn - i2; unsigned int iend = (sv.size()-startColumn > i2 ) ? input.size() : i2 - startColumn + sv.size(); diff --git a/synapse/SeqSynHandler.cpp b/synapse/SeqSynHandler.cpp index e6ca94f8..f31f9117 100644 --- a/synapse/SeqSynHandler.cpp +++ b/synapse/SeqSynHandler.cpp @@ -8,6 +8,7 @@ **********************************************************************/ #include <queue> +#include "global.h" #include "header.h" #include "Synapse.h" #include "SynEvent.h" @@ -105,6 +106,29 @@ const Cinfo* SeqSynHandler::initCinfo() &SeqSynHandler::setSequenceScale, &SeqSynHandler::getSequenceScale ); + static ValueFinfo< SeqSynHandler, vector< unsigned int > > synapseOrder( + "synapseOrder", + "Mapping of synapse input order to spatial order on syn array." + "Entries in this vector are indices which must remain smaller " + "than numSynapses. The system will fix up if you mess up. " + "It does not insist on unique mappings, but these are " + "desirable as outcome is undefined for repeated entries.", + &SeqSynHandler::setSynapseOrder, + &SeqSynHandler::getSynapseOrder + ); + static ValueFinfo< SeqSynHandler, int > synapseOrderOption( + "synapseOrderOption", + "How to do the synapse order remapping. This rule stays in " + "place and guarantees safe mappings even if the number of " + "synapses is altered. Options:\n" + "-2: User ordering.\n" + "-1: Sequential ordering, 0 to numSynapses-1.\n" + "0: Random ordering using existing system seed.\n" + ">0: Random ordering using seed specified by this number\n" + "Default is -1, sequential ordering.", + &SeqSynHandler::setSynapseOrderOption, + &SeqSynHandler::getSynapseOrderOption + ); static ReadOnlyValueFinfo< SeqSynHandler, double > seqActivation( "seqActivation", "Reports summed activation of synaptic channel by sequence", @@ -141,9 +165,11 @@ const Cinfo* SeqSynHandler::initCinfo() &historyTime, // Field &sequenceScale, // Field &baseScale, // Field - &seqActivation, // Field + &synapseOrder, // Field + &synapseOrderOption, // Field + &seqActivation, // ReadOnlyField &plasticityScale, // Field - &weightScaleVec, // Field + &weightScaleVec, // ReadOnlyField &kernel, // ReadOnlyField &history // ReadOnlyField }; @@ -172,10 +198,11 @@ SeqSynHandler::SeqSynHandler() kernelWidth_( 5 ), historyTime_( 2.0 ), seqDt_ ( 1.0 ), - sequenceScale_( 1.0 ), baseScale_( 0.0 ), + sequenceScale_( 1.0 ), plasticityScale_( 0.0 ), - seqActivation_( 0.0 ) + seqActivation_( 0.0 ), + synapseOrderOption_( -1 ) // sequential ordering { history_.resize( numHistory(), 0 ); } @@ -208,6 +235,7 @@ void SeqSynHandler::vSetNumSynapses( const unsigned int v ) history_.resize( numHistory(), v ); latestSpikes_.resize( v, 0.0 ); weightScaleVec_.resize( v, 0.0 ); + refillSynapseOrder( v ); updateKernel(); } @@ -227,6 +255,65 @@ Synapse* SeqSynHandler::vGetSynapse( unsigned int i ) } ////////////////////////////////////////////////////////////////////// + +// Checks for numbers bigger than the size. Replaces with +// values within the range that have not yet been used. +void SeqSynHandler::fixSynapseOrder() +{ + unsigned int sz = synapseOrder_.size(); + vector< unsigned int > availableEntries( sz ); + iota( availableEntries.begin(), availableEntries.end(), 0 ); + for( unsigned int i = 0; i < sz; ++i ) { + if ( synapseOrder_[i] < sz ) + availableEntries[ synapseOrder_[i] ] = sz; + } + vector< unsigned int > ae; + for( unsigned int i = 0; i < sz; ++i ) + if ( availableEntries[i] < sz ) + ae.push_back( availableEntries[i] ); + + auto jj = ae.begin(); + for( unsigned int i = 0; i < sz; ++i ) { + if ( synapseOrder_[i] >= sz ) + synapseOrder_[i] = *jj++; + } +} + +// Beautiful snippet from Lukasz Wiklendt on StackOverflow. Returns order +// of entries in a vector. +template <typename T> vector<size_t> sort_indexes(const vector<T> &v) { + // initialize original index locations + vector<size_t> idx(v.size()); + iota(idx.begin(), idx.end(), 0); + // sort indexes based on comparing values in v + sort(idx.begin(), idx.end(), + [&v](size_t i1, size_t i2) {return v[i1] < v[i2];}); + return idx; +} + +void SeqSynHandler::refillSynapseOrder( unsigned int newSize ) +{ + if ( synapseOrderOption_ <= -2 ) { // User order + synapseOrder_.resize( newSize, newSize ); + fixSynapseOrder(); + } else if ( synapseOrderOption_ == -1 ) { // Ordered + synapseOrder_.resize( newSize ); + for ( unsigned int i = 0 ; i < newSize; ++i ) + synapseOrder_[i] = i; + } else { + synapseOrder_.resize( newSize ); + if ( synapseOrderOption_ > 0 ) { // Specify seed explicitly + moose::mtseed( synapseOrderOption_ ); + } + vector< double > x; + for ( unsigned int i = 0; i < newSize; ++i ) + x.push_back( moose::mtrand() ); + auto idx = sort_indexes< double >( x ); + for ( unsigned int i = 0; i < newSize; ++i ) + synapseOrder_[i] = idx[i]; + } +} + void SeqSynHandler::updateKernel() { if ( kernelEquation_ == "" || seqDt_ < 1e-9 || historyTime_ < 1e-9 ) @@ -362,6 +449,29 @@ vector< double > SeqSynHandler::getHistory() const return ret; } +void SeqSynHandler::setSynapseOrder( vector< unsigned int > v ) +{ + synapseOrder_ = v; + fixSynapseOrder(); + synapseOrderOption_ = -2; // Set the flag to say it is User defined. +} + +vector< unsigned int > SeqSynHandler::getSynapseOrder() const +{ + return synapseOrder_; +} + +void SeqSynHandler::setSynapseOrderOption( int v ) +{ + synapseOrderOption_ = v; + refillSynapseOrder( synapseOrder_.size() ); +} + +int SeqSynHandler::getSynapseOrderOption() const +{ + return synapseOrderOption_; +} + ///////////////////////////////////////////////////////////////////// void SeqSynHandler::addSpike(unsigned int index, double time, double weight) @@ -373,7 +483,9 @@ void SeqSynHandler::addSpike(unsigned int index, double time, double weight) // slice. For now, to get it going for LIF neurons, this will do. // Even in the general case we will probably have a very wide window // for the latestSpikes slice. - latestSpikes_[index] += weight; + // + // Here we reorder the entries in latestSpikes by the synapse order. + latestSpikes_[ synapseOrder_[index] ] += weight; } unsigned int SeqSynHandler::addSynapse() diff --git a/synapse/SeqSynHandler.h b/synapse/SeqSynHandler.h index 73578b04..45217ba0 100644 --- a/synapse/SeqSynHandler.h +++ b/synapse/SeqSynHandler.h @@ -59,6 +59,10 @@ class SeqSynHandler: public SynHandlerBase double getBaseScale() const; void setSequenceScale( double v ); double getSequenceScale() const; + void setSynapseOrder( vector< unsigned int> v ); + vector< unsigned int> getSynapseOrder() const; + void setSynapseOrderOption( int v ); + int getSynapseOrderOption() const; double getSeqActivation() const; // summed activation of syn chan void setPlasticityScale( double v ); double getPlasticityScale() const; @@ -69,6 +73,8 @@ class SeqSynHandler: public SynHandlerBase //////////////////////////////////////////////////////////////// // Utility func int numHistory() const; + void refillSynapseOrder( unsigned int newSize ); + void fixSynapseOrder(); //////////////////////////////////////////////////////////////// static const Cinfo* initCinfo(); private: @@ -116,8 +122,23 @@ class SeqSynHandler: public SynHandlerBase vector< double > latestSpikes_; /////////////////////////////////////////// - vector< vector< double > > kernel_; //Kernel for seq selectivity - RollingMatrix history_; // Rows = time; cols = synInputs + vector< vector< double > > kernel_; ///Kernel for seq selectivity + RollingMatrix history_; /// Rows = time; cols = synInputs + /** + * Remaps synapse order to avoid correlations based on presynaptic + * object Id order, or on connection building order. This + * undesirable ordering occurs even when random synaptic + * projections are used. User can alter as preferred. This is + * simply a look up table so that the incoming synapse index is + * remapped: index_on_Handler = synapseOrder_[original_syn_index] + * This must only have numbers from zero to numSynapses, and should + * normally have all the numbers. + */ + vector< unsigned int > synapseOrder_; + + /// Options: -2: User. -1: ordered. 0: random by system seed. + /// > 0: Random by seed specified by this number + int synapseOrderOption_; vector< Synapse > synapses_; priority_queue< PreSynEvent, vector< PreSynEvent >, CompareSynEvent > events_; diff --git a/synapse/testSynapse.cpp b/synapse/testSynapse.cpp index 944525ff..b39b87bd 100644 --- a/synapse/testSynapse.cpp +++ b/synapse/testSynapse.cpp @@ -99,32 +99,44 @@ void testRollingMatrix() for ( int i = 0; i < nr; ++i ) input[i] = i + 1; - assert( doubleEq( rm.dotProduct( input, 0, 0 ), 0.0 ) ); - assert( doubleEq( rm.dotProduct( input, 1, 0 ), 1.0 ) ); - assert( doubleEq( rm.dotProduct( input, 2, 0 ), 4.0 ) ); - assert( doubleEq( rm.dotProduct( input, 3, 0 ), 9.0 ) ); - assert( doubleEq( rm.dotProduct( input, 4, 0 ), 16.0 ) ); - assert( doubleEq( rm.dotProduct( input, 4, 1 ), 12.0 ) ); - assert( doubleEq( rm.dotProduct( input, 4, 2 ), 8.0 ) ); - assert( doubleEq( rm.dotProduct( input, 4, 3 ), 4.0 ) ); - assert( doubleEq( rm.dotProduct( input, 4, 4 ), 0.0 ) ); - + assert( doubleEq( rm.dotProduct( input, 0, 5 ), 0.0 ) ); + assert( doubleEq( rm.dotProduct( input, 1, 5 ), 1.0 ) ); + assert( doubleEq( rm.dotProduct( input, 2, 5 ), 4.0 ) ); + assert( doubleEq( rm.dotProduct( input, 3, 5 ), 9.0 ) ); + assert( doubleEq( rm.dotProduct( input, 4, 5 ), 16.0 ) ); + assert( doubleEq( rm.dotProduct( input, 4, 6 ), 12.0 ) ); + assert( doubleEq( rm.dotProduct( input, 4, 7 ), 8.0 ) ); + assert( doubleEq( rm.dotProduct( input, 4, 8 ), 4.0 ) ); + assert( doubleEq( rm.dotProduct( input, 4, 9 ), 0.0 ) ); + + // Note that the input and the row are aligned at col=5, the + // middle of the input vector. rm.sumIntoRow( input, 0 ); // input == [1234500000] vector< double > corr; rm.correl( corr, input, 4 ); // rm[4] == [00040000] - assert( doubleEq( corr[0], 16.0 ) ); - assert( doubleEq( corr[1], 12.0 ) ); - assert( doubleEq( corr[2], 8.0 ) ); - assert( doubleEq( corr[3], 4.0 ) ); - assert( doubleEq( corr[4], 0.0 ) ); + assert( doubleEq( corr[0], 0.0 ) ); + assert( doubleEq( corr[1], 0.0 ) ); + assert( doubleEq( corr[2], 0.0 ) ); + assert( doubleEq( corr[3], 0.0 ) ); + assert( doubleEq( corr[4], 20.0 ) ); + assert( doubleEq( corr[5], 16.0 ) ); + assert( doubleEq( corr[6], 12.0 ) ); + assert( doubleEq( corr[7], 8.0 ) ); + assert( doubleEq( corr[8], 4.0 ) ); + assert( doubleEq( corr[9], 0.0 ) ); corr.assign( corr.size(), 0 ); rm.correl( corr, input, 0 ); // rm[0] == [1234500000] - assert( doubleEq( corr[0], 55.0 ) ); - assert( doubleEq( corr[1], 40.0 ) ); - assert( doubleEq( corr[2], 26.0 ) ); - assert( doubleEq( corr[3], 14.0 ) ); - assert( doubleEq( corr[4], 5.0 ) ); + assert( doubleEq( corr[0], 0.0 ) ); + assert( doubleEq( corr[1], 5.0 ) ); + assert( doubleEq( corr[2], 14.0 ) ); + assert( doubleEq( corr[3], 26.0 ) ); + assert( doubleEq( corr[4], 40.0 ) ); + assert( doubleEq( corr[5], 55.0 ) ); + assert( doubleEq( corr[6], 40.0 ) ); + assert( doubleEq( corr[7], 26.0 ) ); + assert( doubleEq( corr[8], 14.0 ) ); + assert( doubleEq( corr[9], 5.0 ) ); cout << "." << flush; } @@ -158,14 +170,12 @@ void testSeqSynapse() cout << "." << flush; - // FIXME: See issue BhallaLab/moose-core#174 - // ssh.setResponseScale( 1.0 ); + ssh.setBaseScale( 1.0 ); + ssh.setSequenceScale( 1.0 ); for ( int i = 0; i < numSyn; ++i ) { ssh.addSpike( i, 0.0, 1.0 ); } - - // FIXME: See issue BhallaLab/moose-core#174 - // ssh.setWeightScale( 1.0 ); + ssh.setPlasticityScale( 1.0 ); ProcInfo p; Eref sheller( Id().eref() ); @@ -177,14 +187,13 @@ void testSeqSynapse() // Here we correlate the vector [1,1,1,1,1,1,1,1,1,1,1] with // the kernel [4,1,-1,-1,-1] // Other lines are zeros. - // Should really make the kernel mapping symmetrical. - assert( doubleEq( ssh.getSeqActivation(), 28.0 ) ); + assert( doubleEq( ssh.getSeqActivation(), 14.0 ) ); vector< double > wts = ssh.getWeightScaleVec(); - for ( int i = 0; i < numSyn-4; ++i ) + for ( int i = 2; i < numSyn-2; ++i ) assert( doubleEq( wts[i], 2.0 ) ); - assert( doubleEq( wts[6], 3 ) ); // Edge effects. Last -1 vanishes. - assert( doubleEq( wts[7], 4 ) ); // Edge effects. - assert( doubleEq( wts[8], 5 ) ); // Edge effects. + assert( doubleEq( wts[0], -3 ) ); // Edge effects. + assert( doubleEq( wts[1], -2 ) ); // Edge effects. + assert( doubleEq( wts[8], 3 ) ); // Edge effects. assert( doubleEq( wts[9], 4 ) ); // Edge effects. cout << "." << flush; -- GitLab