From d0e1cee1d4e62b656772c77fc42e0cd7afad8f66 Mon Sep 17 00:00:00 2001 From: Dilawar Singh <dilawars@ncbs.res.in> Date: Fri, 23 Jun 2017 20:31:42 +0530 Subject: [PATCH] Squashed 'moose-core/' changes from ba97d4c..d1130b7 d1130b7 Merge branch 'master' of github.com:BhallaLab/moose-core 967ac3b Added VERSION info moose.version( ) or moose.__version__ returns the version. It was lost somewhere in rrefactoring the code. 457850e Added version( ) and __version__ string. 2625fd0 Added `moose.test` to test `moose-examples` online (#189) 2a822a2 Added assertion in test case and remove import of matplotlib. BhallaLab/moose#221. 2484214 absolute imports are forced with python2 as well. 6c92901 All tests passes locally with python3. bd78e14 Fixes to import statements. 5c3811e Print time information as well. a7e715c Inbuilt moose.test( ) functions to run moose-examples. BhallaLab/moose-core#184. c424e0d Fixes to chemUtil import. f29e35e Merge branch 'master' of github.com:BhallaLab/moose-core 087aad0 moose.Compartment -> moose.element( ) in couple of more place. One more (#187) d618fe6 Merge branch 'master' into master 4aca08a Merge branch 'master' of github.com:BhallaLab/moose-core b8266b3 Fixes to test failure. Not sure if it is correct. BhallaLab/moose#218 . 56870e8 Merge branch 'master' of github.com:BhallaLab/moose-core d1e37cb Changed the assert statement. Not sure if this is correct to do BhallaLab/moose-core#218. Need to ask developer for confirmation. cf44570 We are no longer testing Makefile base flow. Only cmake will be tested from now on. cf7ff18 moose.Compartment -> moose.element( ) in couple of more place. One more scripts passes the test now. git-subtree-dir: moose-core git-subtree-split: d1130b78bd744e01d045459adb20d5bcebdb34a0 --- hsolve/HSolveInterface.cpp | 1 - python/moose/__init__.py | 33 +- python/moose/moose.py | 39 +- python/moose/moose_test.py | 191 +++++++++ python/moose/neuroml/NetworkML.py | 8 +- python/moose/plot_utils.py | 65 +-- python/moose/sim_utils.py | 76 ---- python/moose/utils.py | 453 ++++++++------------ python/moose/verification_utils.py | 265 ------------ tests/python/test_hsolve_externalCalcium.py | 22 +- 10 files changed, 437 insertions(+), 716 deletions(-) create mode 100644 python/moose/moose_test.py delete mode 100644 python/moose/sim_utils.py delete mode 100644 python/moose/verification_utils.py diff --git a/hsolve/HSolveInterface.cpp b/hsolve/HSolveInterface.cpp index c5bf4d37..5a8e8e3c 100644 --- a/hsolve/HSolveInterface.cpp +++ b/hsolve/HSolveInterface.cpp @@ -247,7 +247,6 @@ void HSolve::addConc( Id id, double conc ) { unsigned int index = localIndex( id ); assert( index < externalCalcium_.size() ); - externalCalcium_[ index ] = conc; } diff --git a/python/moose/__init__.py b/python/moose/__init__.py index 2e2f6772..6bd8517a 100644 --- a/python/moose/__init__.py +++ b/python/moose/__init__.py @@ -1,32 +1,7 @@ -""" -How to use the documentation ----------------------------- +from __future__ import absolute_import, division, print_function -MOOSE documentation is split into Python documentation and builtin -documentation. The functions and classes that are only part of the -Python interface can be viewed via Python's builtin ``help`` -function:: +# Bring moose.py functions into global namespace. ->>> help(moose.connect) +from moose.moose import * -The documentation built into main C++ code of MOOSE can be accessed -via the module function ``doc``:: - ->>> moose.doc('Neutral') - -To get documentation about a particular field:: - ->>> moose.doc('Neutral.childMsg') - -Builtin functions and classes in moose module (Python only) ------------------------------------------------------------ - -""" -from .moose import * - -# Wrapper to get moose version information. -__version__ = moose._moose.__version__ - -VERSION = moose._moose.VERSION - -# NOTE: No module should be imported here. Use moose.py to write imports. +__version__ = moose.moose.version( ) diff --git a/python/moose/moose.py b/python/moose/moose.py index 0957638d..99babb8a 100644 --- a/python/moose/moose.py +++ b/python/moose/moose.py @@ -1,24 +1,29 @@ -# moose.py --- -# This is the primary moose module. It wraps _moose.so and adds some -# utility functions. +from __future__ import print_function, division, absolute_import -# Filename: moose.py # Author: Subhasis Ray # Maintainer: Dilawar Singh, Harsha Rani, Upi Bhalla -from __future__ import print_function from contextlib import closing import warnings import platform import pydoc import os from io import StringIO -from collections import defaultdict -from . import _moose -from ._moose import * -import __main__ as main -from .genesis import writeKkit -from . import SBML + +import moose.SBML.readSBML as _readSBML +import moose.SBML.writeSBML as _writeSBML +import moose.genesis.writeKkit as _writeKkit +import moose.chemUtil as _chemUtil + +# Import function from C++ module into moose namespace. +from moose._moose import * + +def version( ): + return VERSION + +# Tests +from moose.moose_test import test + sequence_types = ['vector<double>', 'vector<int>', 'vector<long>', @@ -43,8 +48,6 @@ known_types = ['void', 'melement'] + sequence_types # SBML related functions. - - def mooseReadSBML(filepath, loadpath, solver='ee'): """Load SBML model. @@ -55,7 +58,7 @@ def mooseReadSBML(filepath, loadpath, solver='ee'): solver -- Solver to use (default 'ee' ) \n """ - return SBML.readSBML.mooseReadSBML( filepath, loadpath, solver ) + return _readSBML.mooseReadSBML( filepath, loadpath, solver ) def mooseWriteSBML(modelpath, filepath, sceneitems={}): @@ -74,7 +77,7 @@ def mooseWriteSBML(modelpath, filepath, sceneitems={}): --- else, auto-coordinates is used for layout position and passed """ - return SBML.writeSBML.mooseWriteSBML(modelpath, filepath, sceneitems) + return _writeSBML.mooseWriteSBML(modelpath, filepath, sceneitems) def mooseWriteKkit(modelpath, filepath,sceneitems={}): @@ -85,7 +88,7 @@ def mooseWriteKkit(modelpath, filepath,sceneitems={}): modelpath -- model path in moose \n filepath -- Path of output file. """ - return writeKkit.mooseWriteKkit(modelpath, filepath,sceneitems) + return _writeKkit.mooseWriteKkit(modelpath, filepath,sceneitems) def moosedeleteChemSolver(modelpath): @@ -94,7 +97,7 @@ def moosedeleteChemSolver(modelpath): this should be followed by mooseaddChemSolver for add solvers on to compartment to simulate else default is Exponential Euler (ee) """ - return chemUtil.add_Delete_ChemicalSolver.moosedeleteChemSolver(modelpath) + return _chemUtil.add_Delete_ChemicalSolver.moosedeleteChemSolver(modelpath) def mooseaddChemSolver(modelpath, solver): @@ -108,7 +111,7 @@ def mooseaddChemSolver(modelpath, solver): "Runge Kutta" ("gsl") """ - return chemUtil.add_Delete_ChemicalSolver.mooseaddChemSolver(modelpath, solver) + return _chemUtil.add_Delete_ChemicalSolver.mooseaddChemSolver(modelpath, solver) ################################################################ # Wrappers for global functions diff --git a/python/moose/moose_test.py b/python/moose/moose_test.py new file mode 100644 index 00000000..c6ff029f --- /dev/null +++ b/python/moose/moose_test.py @@ -0,0 +1,191 @@ +""" +Test MOOSE installation with moose-examples. + +""" + +from __future__ import print_function + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2016, Dilawar Singh" +__credits__ = ["NCBS Bangalore"] +__license__ = "GNU GPL" +__version__ = "1.0.0" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" +__status__ = "Development" + +import sys +import os +import tempfile +import re +import subprocess +import threading +import signal +import logging +from collections import defaultdict +import time + +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', + datefmt='%m-%d %H:%M', + filename='tests.log', + filemode='w' + ) +console = logging.StreamHandler() +console.setLevel(logging.WARNING) +formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') +console.setFormatter(formatter) +_logger = logging.getLogger('moose.test') +_logger.addHandler(console) + +test_data_url_ = 'https://github.com/BhallaLab/moose-examples/archive/master.zip' +test_repo_url_ = 'https://github.com/BhallaLab/moose-examples' +test_dir_ = os.path.join( tempfile.gettempdir( ), 'moose-examples' ) + +ignored_dict_ = defaultdict( list ) +test_status_ = defaultdict( list ) +total_ = 0 + +matplotlibrc_ = ''' +backend : agg +interactive : True +''' + +# Handle CTRL+C +def signal_handler(signal, frame): + print( 'You pressed Ctrl+C!' ) + print_test_stat( ) + quit(-1) + +signal.signal(signal.SIGINT, signal_handler) + +# Credit: https://stackoverflow.com/a/4825933/1805129 +class Command(object): + def __init__(self, cmd): + self.cmd = cmd + self.process = None + self.fnull = open( os.devnull, 'w' ) + + def __repr__( self ): + return ' '.join( self.cmd ) + + def run(self, timeout): + def target(): + _logger.info( "Running %s" % self ) + self.process = subprocess.Popen( + self.cmd, shell=False + , stdout = self.fnull, stderr = subprocess.STDOUT + ) + self.process.communicate() + + thread = threading.Thread( target = target ) + thread.start() + thread.join(timeout) + if thread.is_alive(): + self.process.terminate() + thread.join() + + return self.process.returncode + +def init_test_dir( ): + global test_dir_ + global test_url_ + if( not os.path.exists( test_dir_ ) ): + os.makedirs( test_dir_ ) + _logger.info( "Donwloading test repository" ) + subprocess.call( + [ 'git', 'clone', '--depth=10', test_repo_url_, test_dir_ ] + ) + os.chdir( test_dir_ ) + +def suitable_for_testing( script ): + with open( script ) as f: + txt = f.read( ) + if not re.search( r'main\(\s*\)', txt ): + _logger.debug( 'Script %s does not contain main( )' % script ) + return False, 'main( ) not found' + if re.search( r'raw_input\(\s*\)', txt ): + _logger.debug( 'Script %s requires user input' % script ) + return False, 'waits for user input' + return True, 'OK' + +def run_test( index, testfile ): + """Run a given test + """ + global test_status_ + global total_ + pyExec = os.environ.get( 'PYTHON_EXECUTABLE', '/usr/bin/python' ) + cmd = Command( [ pyExec, testfile ] ) + ti = time.time( ) + status = cmd.run( timeout = 60 ) + name = os.path.basename( testfile ) + t = time.time( ) - ti + cwd = os.path.dirname( testfile ) + os.chdir( cwd ) + with open( os.path.join( cwd, 'matplotlibrc' ), 'w' ) as f: + _logger.debug( 'Writing matplotlibrc to %s' % cwd ) + f.write( matplotlibrc_ ) + + out = (name + '.' * 50)[:50] + print( '[TEST %3d/%d] %50s %.2f sec ' % (index, total_, out, t), end='' ) + sys.stdout.flush( ) + if status != 0: + if status == -15: + msg = '%2d TIMEOUT' % status + test_status_[ 'TIMED-OUT' ].append( testfile ) + else: + msg = '%2d FAILED' % status + test_status_[ 'FAILED' ].append( testfile ) + print( msg ) + else: + print( '%2d PASSED' % status ) + test_status_[ 'PASSED' ].append( testfile ) + sys.stdout.flush( ) + +def print_test_stat( ): + global test_status_ + for status in test_status_: + print( 'Total %d tests %s' % (len( test_status_[status] ), status ) ) + +def test_all( ): + global test_dir_ + global total_ + scripts = [ ] + for d, ds, fs in os.walk( test_dir_ ): + for f in fs: + if not re.match( r'.+\.py$', f): + continue + filepath = os.path.join( d, f ) + isOK, msg = suitable_for_testing( filepath ) + if isOK: + scripts.append( filepath ) + else: + ignored_dict_[ msg ].append( filepath ) + + for k in ignored_dict_: + _logger.debug( '[INFO] Ignored due to %s' % k ) + _logger.debug( '\n\t'.join( ignored_dict_[ k ] ) ) + + _logger.info( 'Total %d valid tests found' % len( scripts ) ) + total_ = len( scripts ) + for i, s in enumerate( scripts ): + _logger.info( 'Running test : %s' % s ) + run_test(i, s ) + + +def test( ): + """Download and run tests. + + """ + try: + init_test_dir( ) + except Exception as e: + print( '[INFO] Failed to clone moose-examples. Error was %s' % e ) + quit( ) + + test_all( ) + print_test_stat( ) + +if __name__ == '__main__': + test( ) diff --git a/python/moose/neuroml/NetworkML.py b/python/moose/neuroml/NetworkML.py index e2e283f4..b96eeec8 100644 --- a/python/moose/neuroml/NetworkML.py +++ b/python/moose/neuroml/NetworkML.py @@ -156,7 +156,7 @@ class NetworkML(): cell_name = self.populationDict[population][0] segment_path = self.populationDict[population][1][int(cell_id)].path+'/'+\ self.cellSegmentDict[cell_name][0][segment_id][0] - compartment = moose.Compartment(segment_path) + compartment = moose.element(segment_path) _logger.debug("Adding pulse at {0}: {1}".format( segment_path, pulsegen.firstLevel ) ) @@ -226,7 +226,7 @@ class NetworkML(): if childobj.className in ['Compartment','SymCompartment']: ## SymCompartment inherits from Compartment, ## so below wrapping by Compartment() is fine for both Compartment and SymCompartment - child = moose.Compartment(childId) + child = moose.element(childId) x0 = child.x0 y0 = child.y0 x0new = x0*cos(ztheta)-y0*sin(ztheta) @@ -316,7 +316,7 @@ class NetworkML(): weight_override, threshold, delay_override) def connect(self, syn_name, pre_path, post_path, weight, threshold, delay): - postcomp = moose.Compartment(post_path) + postcomp = moose.element(post_path) ## We usually try to reuse an existing SynChan & SynHandler - ## event based SynHandlers have an array of weights and delays and can represent multiple synapses, ## so a new element of the weights and delays array is created @@ -349,7 +349,7 @@ class NetworkML(): if gradedchild is not None and gradedchild.value=='True': # graded synapse interpol = moose.element(syn.path+"/graded_table") #### always connect source to input - else 'cannot create message' error. - precomp = moose.Compartment(pre_path) + precomp = moose.element(pre_path) moose.connect(precomp,"VmOut",interpol,"input") try: tau_table = moose.element(syn.path+'/tau_table') diff --git a/python/moose/plot_utils.py b/python/moose/plot_utils.py index b2740954..556e2487 100644 --- a/python/moose/plot_utils.py +++ b/python/moose/plot_utils.py @@ -1,5 +1,3 @@ - - """plot_utils.py: Some utility function for plotting data in moose. Last modified: Sun Jan 10, 2016 04:04PM @@ -15,10 +13,11 @@ __maintainer__ = "Dilawar Singh" __email__ = "dilawars@ncbs.res.in" __status__ = "Development" -import matplotlib.pyplot as plt -from . import _moose as moose -from . import print_utils as pu import numpy as np +import moose +import print_utils as pu + +import matplotlib.pyplot as plt def plotAscii(yvec, xvec = None, file=None): """Plot two list-like object in terminal using gnuplot. @@ -135,7 +134,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) @@ -233,11 +232,7 @@ def saveRecords(records, xvec = None, **kwargs): pu.info("Done writing data to %s" % outfile) def plotRecords(records, xvec = None, **kwargs): - """plotRecords Plot given records in dictionary. - - :param records: - :param xvec: If None, use moose.Clock to generate xvec. - :param **kwargs: + """Wrapper """ dataDict = {} try: @@ -267,7 +262,7 @@ def plotRecords(records, xvec = None, **kwargs): yvec = dataDict[k].vector plotVector(yvec, xvec, label=k, **kwargs) else: - plt.subplot(len(dataDict), 1, i) + plt.subplot(len(dataDict), 1, i+1) yvec = dataDict[k].vector plotVector(yvec, xvec, label=k, **kwargs) @@ -285,47 +280,15 @@ def plotRecords(records, xvec = None, **kwargs): plt.savefig("%s" % outfile, transparent=True) else: plt.show() + plt.close( ) -def plot_records(data_dict, xvec = None, **kwargs): - """plot_records Plot given dictionary. +def plotTables( records, xvec = None, **kwargs ): + """Plot dictionary of moose.Table/moose.Table2 - :param data_dict: - :param xvec: If None, use moose.Clock to generate xvec. + :param records: A dictionary of moose.Table. All tables must have same + length. + :param xvec: If None, moose.Clock is used to generate time-vector. :param **kwargs: """ - - legend = kwargs.get('legend', True) - outfile = kwargs.get('outfile', None) - subplot = kwargs.get('subplot', False) - filters = [ x.lower() for x in kwargs.get('filter', [])] - - plt.figure(figsize=(10, 1.5*len(data_dict))) - for i, k in enumerate(data_dict): - pu.info("+ Plotting for %s" % k) - plotThis = False - if not filters: plotThis = True - for accept in filters: - if accept in k.lower(): - plotThis = True - break - - if plotThis: - if not subplot: - yvec = data_dict[k] - plotVector(yvec, xvec, label=k, **kwargs) - else: - plt.subplot(len(data_dict), 1, i) - yvec = data_dict[k] - plotVector(yvec, xvec, label=k, **kwargs) - if subplot: - try: - plt.tight_layout() - except: pass - - if outfile: - pu.info("Writing plot to %s" % outfile) - plt.savefig("%s" % outfile, transparent=True) - else: - plt.show() - + return plotRecords( records, xvec, **kwargs ) diff --git a/python/moose/sim_utils.py b/python/moose/sim_utils.py deleted file mode 100644 index 0fd637d7..00000000 --- a/python/moose/sim_utils.py +++ /dev/null @@ -1,76 +0,0 @@ - - -"""sim_utils.py: - Helper function related with simulation. - -Last modified: Sat Jan 18, 2014 05:01PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -from . import _moose -from . import print_utils -from . import verification_utils - -def recordTarget(tablePath, target, field = 'vm', **kwargs): - """Setup a table to record at given path. - - Make sure that all root paths in tablePath exists. - - Returns a table. - """ - - # If target is not an moose object but a string representing intended path - # then we need to fetch the object first. - - if type( target) == str: - if not _moose.exists(target): - msg = "Given target `{}` does not exists. ".format( target ) - raise RuntimeError( msg ) - else: - target = _moose.Neutral( target ) - - assert target.path, "Target must have a valid moose path." - - table = _moose.Table( tablePath ) - assert table - - # Sanities field. - if field == "output": - pass - elif 'get' not in field: - field = 'get'+field[0].upper()+field[1:] - else: - field = field[:2]+field[3].upper()+field[4:] - try: - print_utils.dump("TABLE" - , "Connecting table {} to target {} field {}".format( - table.path - , target.path - , field - ) - ) - table.connect( 'requestOut', target, field ) - except Exception as e: - debug.dump("ERROR" - , [ "Failed to connect table to target" - , e - ] - ) - raise e - assert table, "Moose is not able to create a recording table" - return table - - -def run(simTime, verify=False): - if verify: - verification_utils.verify() - _moose.start(simTime) diff --git a/python/moose/utils.py b/python/moose/utils.py index a3f6dd94..91776193 100644 --- a/python/moose/utils.py +++ b/python/moose/utils.py @@ -1,11 +1,14 @@ -"""utils.py: +from __future__ import print_function, division +from __future__ import absolute_import - Utility functions for moose. +""" +utils.py: + +Utility functions for moose. - Last modified: Mon Feb 23, 2015 08:34PM +NOTE: Some function might break because unicode is default string in python3. """ -from __future__ import print_function __author__ = 'Subhasis Ray, Aditya Gilra, Dilawar Singh' __copyright__ = "Copyright 2013, NCBS Bangalore" @@ -13,110 +16,30 @@ __credits__ = ["NCBS Bangalore", "Bhalla Lab"] __license__ = "GPL" __version__ = "1.0.0" - import types import parser import token import symbol -import string import os import math import warnings from datetime import datetime from collections import defaultdict +import re -from . import _moose +from moose.moose_constants import * -## Fix the backend. -import matplotlib +# Make these import non-important. try: - from .plot_utils import * + from moose.plot_utils import * except Exception as e: - warnings.warn("Failed to importing plotting utilities: %s" % e) + pass try: - from .verification_utils import verify -except: + from moose.print_utils import * +except Exception as e: pass -try: from .print_utils import * -except: pass - -try: from .sim_utils import * -except: pass - -from .moose_constants import * - -import re - -# from PyQt4 import QtCore, Qt - -# tableEmitter = QtCore.QObject() -# Harsha: Moved this fun from default to pymoose/moose/utils.py -#def createRecordingTable(element, field, _recordDict, _reverseDict,dataRoot='/data'): -# -# This does not belong here. Qt is for GUI and such things should go -# under gui directory. Keep the core modules clean. -# -Subha. Wed Oct 1 16:37:26 IST 2014 - - -# def create(model, graph, element, field): -# """Create table to record `field` from element `element` - -# Tables are created under `dataRoot`, the names are generally -# created by removing `/model` in the beginning of `elementPath` -# and replacing `/` with `_`. If this conflicts with an existing -# table, the id value of the target element (elementPath) is -# appended to the name. -# """ - -# # if not _moose.exists(dataroot): -# # _moose.Neutral(dataroot) -# ''' -# if len(field) == 0 or ((element, field) in self._recordDict): -# return -# ''' -# field = lst = [word[0].upper() + word[1:] for word in field.split()] -# field = " ".join(lst) - -# if len(field) == 0 or len(element.neighbors['get%s'%(field)]) > 0: -# return -# # The table path is not foolproof - conflict is -# # possible: e.g. /model/test_object and -# # /model/test/object will map to same table. So we -# # check for existing table without element field -# # path in recording dict. -# relativePath = element.path.partition(modelroot)[-1] -# if relativePath.startswith('/'): -# relativePath = relativePath[1:] - -# #Convert to camelcase - -# tablePath = relativePath.replace('/', '_') + '.' + field -# tablePath = re.sub('.', lambda m: {'[':'_', ']':'_'}.get(m.group(), m.group()),tablePath) - -# if tablePath.startswith("_0__"): -# tablePath = tablePath[4:] - -# tablePath = dataroot + '/' +tablePath -# #tablePath = dataroot+'/'+element.name+'.'+field[:2] -# if _moose.exists(tablePath): -# tablePath = '%s_%d' % (tablePath, element.getId().value) - -# if not _moose.exists(tablePath): -# table = _moose.Table(tablePath) -# print 'Created', table.path, 'for plotting', '%s.%s' % (element.path, field) -# target = element -# _moose.connect(table, 'requestOut', target, 'get%s' % (field)) - -# tableEmitter.emit(QtCore.SIGNAL('tableCreated()')) -# #tableCreated.emit() -# return True -# #self.emit(QtCore.SIGNAL('tableCreated(PyQt_PyObject)')) -# #self.created.emit() - -# return False - def create_table_path(model, graph, element, field): @@ -151,14 +74,14 @@ def create_table(tablePath, element, field,tableType): table, the id value of the target element (elementPath) is appended to the name. """ - if _moose.exists(tablePath): - table = _moose.element(tablePath) + if moose.exists(tablePath): + table = moose.element(tablePath) else: if tableType == "Table2": - table = _moose.Table2(tablePath) + table = moose.Table2(tablePath) elif tableType == "Table": - table = _moose.Table(tablePath) - _moose.connect(table, 'requestOut', element, 'get%s' % (field)) + table = moose.Table(tablePath) + moose.connect(table, 'requestOut', element, 'get%s' % (field)) return table def readtable(table, filename, separator=None): @@ -195,7 +118,7 @@ def getfields(moose_object): return fields def findAllBut(moose_wildcard, stringToExclude): - allValidObjects = _moose.wildcardFind(moose_wildcard) + allValidObjects = moose.wildcardFind(moose_wildcard) refinedList = [] for validObject in allValidObjects: if validObject.path.find(stringToExclude) == -1: @@ -261,17 +184,17 @@ def apply_to_tree(moose_wildcard, python_filter=None, value=None): """ if not isinstance(moose_wildcard, str): raise TypeError('moose_wildcard must be a string.') - id_list = _moose.getWildcardList(moose_wildcard, True) + id_list = moose.getWildcardList(moose_wildcard, True) if isinstance(python_filter, types.LambdaType): id_list = [moose_id for moose_id in id_list if python_filter(moose_id)] elif isinstance(python_filter, str): - id_list = [moose_id for moose_id in id_list if hasattr(eval('_moose.%s(moose_id)' % (_moose.Neutral(moose_id).className)), python_filter)] + id_list = [moose_id for moose_id in id_list if hasattr(eval('moose.%s(moose_id)' % (moose.Neutral(moose_id).className)), python_filter)] else: pass if isinstance(value, types.LambdaType): if isinstance(python_filter, str): for moose_id in id_list: - moose_obj = eval('_moose.%s(moose_id)' % (_moose.Neutral(moose_id).className)) + moose_obj = eval('moose.%s(moose_id)' % (moose.Neutral(moose_id).className)) setattr(moose_obj, python_filter, value(moose_id)) else: for moose_id in id_list: @@ -279,7 +202,7 @@ def apply_to_tree(moose_wildcard, python_filter=None, value=None): else: if isinstance(python_filter, str): for moose_id in id_list: - moose_obj = eval('_moose.%s(moose_id)' % (_moose.Neutral(moose_id).className)) + moose_obj = eval('moose.%s(moose_id)' % (moose.Neutral(moose_id).className)) setattr(moose_obj, python_filter, value) else: raise TypeError('Second argument must be a string specifying a field to assign to when third argument is a value') @@ -299,7 +222,7 @@ def tweak_field(moose_wildcard, field, assignment_string): """ if not isinstance(moose_wildcard, str): raise TypeError('moose_wildcard must be a string.') - id_list = _moose.getWildcardList(moose_wildcard, True) + id_list = moose.getWildcardList(moose_wildcard, True) expression = parser.expr(assignment_string) expr_list = expression.tolist() # This is a hack: I just tried out some possible syntax trees and @@ -319,9 +242,9 @@ def tweak_field(moose_wildcard, field, assignment_string): new_expr = parser.sequence2st(tmp) code = new_expr.compile() for moose_id in id_list: - moose_obj = eval('_moose.%s(moose_id)' % (_moose.Neutral(moose_id).className)) + moose_obj = eval('moose.%s(moose_id)' % (moose.Neutral(moose_id).className)) value = eval(code) - _moose.setField(moose_id, field, str(value)) + moose.setField(moose_id, field, str(value)) # 2012-01-11 19:20:39 (+0530) Subha: checked for compatibility with dh_branch def printtree(root, vchar='|', hchar='__', vcount=1, depth=0, prefix='', is_last=False): @@ -344,7 +267,7 @@ def printtree(root, vchar='|', hchar='__', vcount=1, depth=0, prefix='', is_last is_last - for internal use - should not be explicitly passed. """ - root = _moose.element(root) + root = moose.element(root) # print('%s: "%s"' % (root, root.children)) for i in range(vcount): print(prefix) @@ -363,7 +286,7 @@ def printtree(root, vchar='|', hchar='__', vcount=1, depth=0, prefix='', is_last children = [] for child_vec in root.children: try: - child = _moose.element(child_vec) + child = moose.element(child_vec) children.append(child) except TypeError: pass @@ -384,7 +307,7 @@ def df_traverse(root, operation, *args): return operation(root, *args) for child in root.children: - childNode = _moose.Neutral(child) + childNode = moose.Neutral(child) df_traverse(childNode, operation, *args) root._visited = True @@ -401,8 +324,8 @@ def autoposition(root): compartments overlapping in space. """ - compartments = _moose.wildcardFind('%s/##[TYPE=Compartment]' % (root.path)) - stack = [compartment for compartment in map(_moose.element, compartments) + compartments = moose.wildcardFind('%s/##[TYPE=Compartment]' % (root.path)) + stack = [compartment for compartment in map(moose.element, compartments) if len(compartment.neighbors['axial']) == 0] if len(stack) != 1: raise Exception('There must be one and only one top level compartment. Found %d' % (len(topcomp_list))) @@ -424,7 +347,7 @@ def autoposition(root): comp.x, comp.y, comp.z, = comp.x0, comp.y0, comp.z0 + comp.diameter/2.0 # We take z == 0 as an indicator that this compartment has not # been processed before - saves against inadvertent loops. - stack.extend([childcomp for childcomp in map(_moose.element, comp.neighbors['raxial']) if childcomp.z == 0]) + stack.extend([childcomp for childcomp in map(moose.element, comp.neighbors['raxial']) if childcomp.z == 0]) return ret @@ -475,7 +398,7 @@ def readcell_scrambled(filename, target, method='ee'): print('#########"', current, '": ', data[current]) tmpfile.write(data[current]) tmpfile.close() - ret = _moose.loadModel(tmpfilename, target, method) + ret = moose.loadModel(tmpfilename, target, method) return ret ## Subha: In many scenarios resetSim is too rigid and focussed on @@ -496,7 +419,7 @@ def updateTicks(tickDtMap): """ for tickNo, dt in list(tickDtMap.items()): if tickNo >= 0 and dt > 0.0: - _moose.setClock(tickNo, dt) + moose.setClock(tickNo, dt) if all([(v == 0) for v in list(tickDtMap.values())]): setDefaultDt() @@ -514,14 +437,14 @@ def assignTicks(tickTargetMap): for tickNo, target in list(tickTargetMap.items()): if not isinstance(target, str): if len(target) == 1: - _moose.useClock(tickNo, target[0], 'process') + moose.useClock(tickNo, target[0], 'process') elif len(target) == 2: - _moose.useClock(tickNo, target[0], target[1]) + moose.useClock(tickNo, target[0], target[1]) else: - _moose.useClock(tickNo, target, 'process') + moose.useClock(tickNo, target, 'process') # # This is a hack, we need saner way of scheduling - # ticks = _moose.vec('/clock/tick') + # ticks = moose.vec('/clock/tick') # valid = [] # for ii in range(ticks[0].localNumField): # if ticks[ii].dt > 0: @@ -547,67 +470,67 @@ def setDefaultDt(elecdt=1e-5, chemdt=0.01, tabdt=1e-5, plotdt1=1.0, plotdt2=0.25 plotdt2: dt for electrical simulations """ - _moose.setClock(0, elecdt) - _moose.setClock(1, elecdt) - _moose.setClock(2, elecdt) - _moose.setClock(3, elecdt) - _moose.setClock(4, chemdt) - _moose.setClock(5, chemdt) - _moose.setClock(6, tabdt) - _moose.setClock(7, tabdt) - _moose.setClock(8, plotdt1) # kinetics sim - _moose.setClock(9, plotdt2) # electrical sim + moose.setClock(0, elecdt) + moose.setClock(1, elecdt) + moose.setClock(2, elecdt) + moose.setClock(3, elecdt) + moose.setClock(4, chemdt) + moose.setClock(5, chemdt) + moose.setClock(6, tabdt) + moose.setClock(7, tabdt) + moose.setClock(8, plotdt1) # kinetics sim + moose.setClock(9, plotdt2) # electrical sim def assignDefaultTicks(modelRoot='/model', dataRoot='/data', solver='hsolve'): - if isinstance(modelRoot, _moose.melement) or isinstance(modelRoot, _moose.vec): + if isinstance(modelRoot, moose.melement) or isinstance(modelRoot, moose.vec): modelRoot = modelRoot.path - if isinstance(dataRoot, _moose.melement) or isinstance(dataRoot, _moose.vec): + if isinstance(dataRoot, moose.melement) or isinstance(dataRoot, moose.vec): dataRoot = dataRoot.path - if solver != 'hsolve' or len(_moose.wildcardFind('%s/##[ISA=HSolve]' % (modelRoot))) == 0: - _moose.useClock(0, '%s/##[ISA=Compartment]' % (modelRoot), 'init') - _moose.useClock(1, '%s/##[ISA=Compartment]' % (modelRoot), 'process') - _moose.useClock(2, '%s/##[ISA=HHChannel]' % (modelRoot), 'process') - # _moose.useClock(2, '%s/##[ISA=ChanBase]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=IzhikevichNrn]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=GapJunction]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=HSolve]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=LeakyIaF]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=IntFire]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=SpikeGen]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=PulseGen]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=StimulusTable]' % (modelRoot), 'process') - _moose.useClock(1, '%s/##[ISA=TimeTable]' % (modelRoot), 'process') - _moose.useClock(2, '%s/##[ISA=HHChannel2D]' % (modelRoot), 'process') - _moose.useClock(2, '%s/##[ISA=SynChan]' % (modelRoot), 'process') - _moose.useClock(2, '%s/##[ISA=MgBlock]' % (modelRoot), 'process') - _moose.useClock(3, '%s/##[ISA=CaConc]' % (modelRoot), 'process') - _moose.useClock(3, '%s/##[ISA=Func]' % (modelRoot), 'process') + if solver != 'hsolve' or len(moose.wildcardFind('%s/##[ISA=HSolve]' % (modelRoot))) == 0: + moose.useClock(0, '%s/##[ISA=Compartment]' % (modelRoot), 'init') + moose.useClock(1, '%s/##[ISA=Compartment]' % (modelRoot), 'process') + moose.useClock(2, '%s/##[ISA=HHChannel]' % (modelRoot), 'process') + # moose.useClock(2, '%s/##[ISA=ChanBase]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=IzhikevichNrn]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=GapJunction]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=HSolve]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=LeakyIaF]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=IntFire]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=SpikeGen]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=PulseGen]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=StimulusTable]' % (modelRoot), 'process') + moose.useClock(1, '%s/##[ISA=TimeTable]' % (modelRoot), 'process') + moose.useClock(2, '%s/##[ISA=HHChannel2D]' % (modelRoot), 'process') + moose.useClock(2, '%s/##[ISA=SynChan]' % (modelRoot), 'process') + moose.useClock(2, '%s/##[ISA=MgBlock]' % (modelRoot), 'process') + moose.useClock(3, '%s/##[ISA=CaConc]' % (modelRoot), 'process') + moose.useClock(3, '%s/##[ISA=Func]' % (modelRoot), 'process') # The voltage clamp circuit depends critically on the dt used for # computing soma Vm and need to be on a clock with dt=elecdt. - _moose.useClock(0, '%s/##[ISA=DiffAmp]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=VClamp]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=PIDController]' % (modelRoot), 'process') - _moose.useClock(0, '%s/##[ISA=RC]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=DiffAmp]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=VClamp]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=PIDController]' % (modelRoot), 'process') + moose.useClock(0, '%s/##[ISA=RC]' % (modelRoot), 'process') # Special case for kinetics models - kinetics = _moose.wildcardFind('%s/##[FIELD(name)=kinetics]' % modelRoot) + kinetics = moose.wildcardFind('%s/##[FIELD(name)=kinetics]' % modelRoot) if len(kinetics) > 0: # Do nothing for kinetics models - until multiple scheduling issue is fixed. - _moose.useClock(4, '%s/##[ISA!=PoolBase]' % (kinetics[0].path), 'process') - _moose.useClock(5, '%s/##[ISA==PoolBase]' % (kinetics[0].path), 'process') - _moose.useClock(18, '%s/##[ISA=Table2]' % (dataRoot), 'process') + moose.useClock(4, '%s/##[ISA!=PoolBase]' % (kinetics[0].path), 'process') + moose.useClock(5, '%s/##[ISA==PoolBase]' % (kinetics[0].path), 'process') + moose.useClock(18, '%s/##[ISA=Table2]' % (dataRoot), 'process') else: # input() function is called in Table. process() which gets # called at each timestep. When a message is connected # explicitly to input() dest field, it is driven by the sender # and process() adds garbage value to the vector. Hence not to # be scheduled. - for tab in _moose.wildcardFind('%s/##[ISA=Table]' % (dataRoot)): + for tab in moose.wildcardFind('%s/##[ISA=Table]' % (dataRoot)): if len(tab.neighbors['input']) == 0: - _moose.useClock(9, tab.path, 'process') + moose.useClock(9, tab.path, 'process') def stepRun(simtime, steptime, verbose=True, logger=None): """Run the simulation in steps of `steptime` for `simtime`.""" - clock = _moose.Clock('/clock') + clock = moose.Clock('/clock') if verbose: msg = 'Starting simulation for %g' % (simtime) if logger is None: @@ -617,7 +540,7 @@ def stepRun(simtime, steptime, verbose=True, logger=None): ts = datetime.now() while clock.currentTime < simtime - steptime: ts1 = datetime.now() - _moose.start(steptime) + moose.start(steptime) te = datetime.now() td = te - ts1 if verbose: @@ -635,10 +558,10 @@ def stepRun(simtime, steptime, verbose=True, logger=None): print(msg) else: logger.info(msg) - _moose.start(remaining) + moose.start(remaining) te = datetime.now() td = te - ts - dt = min([t for t in _moose.element('/clock').dts if t > 0.0]) + dt = min([t for t in moose.element('/clock').dts if t > 0.0]) if verbose: msg = 'Finished simulation of %g with minimum dt=%g in %g s' % (simtime, dt, td.days * 86400 + td.seconds + 1e-6 * td.microseconds) if logger is None: @@ -654,12 +577,12 @@ def resetSim(simpaths, simdt, plotdt, simmethod='hsolve'): """ For each of the MOOSE paths in simpaths, this sets the clocks and finally resets MOOSE. If simmethod=='hsolve', it sets up hsolve-s for each Neuron under simpaths, and clocks for hsolve-s too. """ print('Solver:', simmethod) - _moose.setClock(INITCLOCK, simdt) - _moose.setClock(ELECCLOCK, simdt) # The hsolve and ee methods use clock 1 - _moose.setClock(CHANCLOCK, simdt) # hsolve uses clock 2 for mg_block, nmdachan and others. - _moose.setClock(POOLCLOCK, simdt) # Ca/ion pools & funcs use clock 3 - _moose.setClock(STIMCLOCK, simdt) # Ca/ion pools & funcs use clock 3 - _moose.setClock(PLOTCLOCK, plotdt) # for tables + moose.setClock(INITCLOCK, simdt) + moose.setClock(ELECCLOCK, simdt) # The hsolve and ee methods use clock 1 + moose.setClock(CHANCLOCK, simdt) # hsolve uses clock 2 for mg_block, nmdachan and others. + moose.setClock(POOLCLOCK, simdt) # Ca/ion pools & funcs use clock 3 + moose.setClock(STIMCLOCK, simdt) # Ca/ion pools & funcs use clock 3 + moose.setClock(PLOTCLOCK, plotdt) # for tables for simpath in simpaths: ## User can connect [qty]Out of an element to input of Table or ## requestOut of Table to get[qty] of the element. @@ -667,46 +590,46 @@ def resetSim(simpaths, simdt, plotdt, simmethod='hsolve'): ## which will send a requestOut and overwrite any value set by input(), ## thus adding garbage value to the vector. Hence schedule only if ## input message is not connected to the Table. - for table in _moose.wildcardFind(simpath+'/##[TYPE=Table]'): + for table in moose.wildcardFind(simpath+'/##[TYPE=Table]'): if len(table.neighbors['input']) == 0: - _moose.useClock(PLOTCLOCK, table.path, 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=PulseGen]', 'process') - _moose.useClock(STIMCLOCK, simpath+'/##[TYPE=DiffAmp]', 'process') - _moose.useClock(STIMCLOCK, simpath+'/##[TYPE=VClamp]', 'process') - _moose.useClock(STIMCLOCK, simpath+'/##[TYPE=PIDController]', 'process') - _moose.useClock(STIMCLOCK, simpath+'/##[TYPE=RC]', 'process') - _moose.useClock(STIMCLOCK, simpath+'/##[TYPE=TimeTable]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=LeakyIaF]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=IntFire]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=IzhikevichNrn]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=SpikeGen]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Interpol]', 'process') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Interpol2D]', 'process') - _moose.useClock(CHANCLOCK, simpath+'/##[TYPE=HHChannel2D]', 'process') - _moose.useClock(CHANCLOCK, simpath+'/##[TYPE=SynChan]', 'process') + moose.useClock(PLOTCLOCK, table.path, 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=PulseGen]', 'process') + moose.useClock(STIMCLOCK, simpath+'/##[TYPE=DiffAmp]', 'process') + moose.useClock(STIMCLOCK, simpath+'/##[TYPE=VClamp]', 'process') + moose.useClock(STIMCLOCK, simpath+'/##[TYPE=PIDController]', 'process') + moose.useClock(STIMCLOCK, simpath+'/##[TYPE=RC]', 'process') + moose.useClock(STIMCLOCK, simpath+'/##[TYPE=TimeTable]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=LeakyIaF]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=IntFire]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=IzhikevichNrn]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=SpikeGen]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Interpol]', 'process') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Interpol2D]', 'process') + moose.useClock(CHANCLOCK, simpath+'/##[TYPE=HHChannel2D]', 'process') + moose.useClock(CHANCLOCK, simpath+'/##[TYPE=SynChan]', 'process') ## If simmethod is not hsolve, set clocks for the biophysics, ## else just put a clock on the hsolve: ## hsolve takes care of the clocks for the biophysics if 'hsolve' not in simmethod.lower(): print('Using exp euler') - _moose.useClock(INITCLOCK, simpath+'/##[TYPE=Compartment]', 'init') - _moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Compartment]', 'process') - _moose.useClock(CHANCLOCK, simpath+'/##[TYPE=HHChannel]', 'process') - _moose.useClock(POOLCLOCK, simpath+'/##[TYPE=CaConc]', 'process') - _moose.useClock(POOLCLOCK, simpath+'/##[TYPE=Func]', 'process') + moose.useClock(INITCLOCK, simpath+'/##[TYPE=Compartment]', 'init') + moose.useClock(ELECCLOCK, simpath+'/##[TYPE=Compartment]', 'process') + moose.useClock(CHANCLOCK, simpath+'/##[TYPE=HHChannel]', 'process') + moose.useClock(POOLCLOCK, simpath+'/##[TYPE=CaConc]', 'process') + moose.useClock(POOLCLOCK, simpath+'/##[TYPE=Func]', 'process') else: # use hsolve, one hsolve for each Neuron print('Using hsolve') - element = _moose.Neutral(simpath) + element = moose.Neutral(simpath) for childid in element.children: - childobj = _moose.Neutral(childid) + childobj = moose.Neutral(childid) classname = childobj.className if classname in ['Neuron']: neuronpath = childobj.path - h = _moose.HSolve( neuronpath+'/solve' ) + h = moose.HSolve( neuronpath+'/solve' ) h.dt = simdt h.target = neuronpath - _moose.useClock(INITCLOCK, h.path, 'process') - _moose.reinit() + moose.useClock(INITCLOCK, h.path, 'process') + moose.reinit() def setupTable(name, obj, qtyname, tables_path=None, threshold=None, spikegen=None): """ Sets up a table with 'name' which stores 'qtyname' field from 'obj'. @@ -714,26 +637,26 @@ def setupTable(name, obj, qtyname, tables_path=None, threshold=None, spikegen=No if tables_path is None: tables_path = obj.path+'/data' ## in case tables_path does not exist, below wrapper will create it - tables_path_obj = _moose.Neutral(tables_path) - qtyTable = _moose.Table(tables_path_obj.path+'/'+name) + tables_path_obj = moose.Neutral(tables_path) + qtyTable = moose.Table(tables_path_obj.path+'/'+name) ## stepMode no longer supported, connect to 'input'/'spike' message dest to record Vm/spiktimes # qtyTable.stepMode = TAB_BUF if spikegen is None: if threshold is None: ## below is wrong! reads qty twice every clock tick! - #_moose.connect( obj, qtyname+'Out', qtyTable, "input") + #moose.connect( obj, qtyname+'Out', qtyTable, "input") ## this is the correct method - _moose.connect( qtyTable, "requestOut", obj, 'get'+qtyname) + moose.connect( qtyTable, "requestOut", obj, 'get'+qtyname) else: ## create new spikegen - spikegen = _moose.SpikeGen(tables_path_obj.path+'/'+name+'_spikegen') + spikegen = moose.SpikeGen(tables_path_obj.path+'/'+name+'_spikegen') ## connect the compartment Vm to the spikegen - _moose.connect(obj,"VmOut",spikegen,"Vm") + moose.connect(obj,"VmOut",spikegen,"Vm") ## spikegens for different synapse_types can have different thresholds spikegen.threshold = threshold spikegen.edgeTriggered = 1 # This ensures that spike is generated only on leading edge. else: - _moose.connect(spikegen,'spikeOut',qtyTable,'input') ## spikeGen gives spiketimes + moose.connect(spikegen,'spikeOut',qtyTable,'input') ## spikeGen gives spiketimes return qtyTable def connectSynapse(compartment, synname, gbar_factor): @@ -741,12 +664,12 @@ def connectSynapse(compartment, synname, gbar_factor): Creates a synname synapse under compartment, sets Gbar*gbar_factor, and attaches to compartment. synname must be a synapse in /library of MOOSE. """ - synapseid = _moose.copy(_moose.SynChan('/library/'+synname),compartment,synname) - synapse = _moose.SynChan(synapseid) + synapseid = moose.copy(moose.SynChan('/library/'+synname),compartment,synname) + synapse = moose.SynChan(synapseid) synapse.Gbar = synapse.Gbar*gbar_factor - synapse_mgblock = _moose.Mstring(synapse.path+'/mgblockStr') + synapse_mgblock = moose.Mstring(synapse.path+'/mgblockStr') if synapse_mgblock.value=='True': # If NMDA synapse based on mgblock, connect to mgblock - mgblock = _moose.Mg_block(synapse.path+'/mgblock') + mgblock = moose.Mg_block(synapse.path+'/mgblock') compartment.connect("channel", mgblock, "channel") else: compartment.connect("channel", synapse, "channel") @@ -754,10 +677,10 @@ def connectSynapse(compartment, synname, gbar_factor): def printNetTree(): """ Prints all the cells under /, and recursive prints the cell tree for each cell. """ - root = _moose.Neutral('/') + root = moose.Neutral('/') for id in root.children: # all subelements of 'root' - if _moose.Neutral(id).className == 'Cell': - cell = _moose.Cell(id) + if moose.Neutral(id).className == 'Cell': + cell = moose.Cell(id) print("-------------------- CELL : ",cell.name," ---------------------------") printCellTree(cell) @@ -773,7 +696,7 @@ def printCellTree(cell): FIXME: no lenght cound on compartment. """ for compartmentid in cell.children: # compartments - comp = _moose.Compartment(compartmentid) + comp = moose.Compartment(compartmentid) print(" |-",comp.path, 'l=',comp.length, 'd=',comp.diameter, 'Rm=',comp.Rm, 'Ra=',comp.Ra, 'Cm=',comp.Cm, 'EM=',comp.Em) #for inmsg in comp.inMessages(): # print " |---", inmsg @@ -786,28 +709,28 @@ def printRecursiveTree(elementid, level): """ Recursive helper function for printCellTree, specify depth/'level' to recurse and print subelements under MOOSE 'elementid'. """ spacefill = ' '*level - element = _moose.Neutral(elementid) + element = moose.Neutral(elementid) for childid in element.children: - childobj = _moose.Neutral(childid) + childobj = moose.Neutral(childid) classname = childobj.className if classname in ['SynChan','KinSynChan']: - childobj = _moose.SynChan(childid) + childobj = moose.SynChan(childid) print(spacefill+"|--", childobj.name, childobj.className, 'Gbar=',childobj.Gbar, 'numSynapses=', childobj.numSynapses) return # Have yet to figure out the children of SynChan, currently not going deeper elif classname in ['HHChannel', 'HHChannel2D']: - childobj = _moose.HHChannel(childid) + childobj = moose.HHChannel(childid) print(spacefill+"|--", childobj.name, childobj.className, 'Gbar=',childobj.Gbar, 'Ek=',childobj.Ek) elif classname in ['CaConc']: - childobj = _moose.CaConc(childid) + childobj = moose.CaConc(childid) print(spacefill+"|--", childobj.name, childobj.className, 'thick=',childobj.thick, 'B=',childobj.B) elif classname in ['Mg_block']: - childobj = _moose.Mg_block(childid) + childobj = moose.Mg_block(childid) print(spacefill+"|--", childobj.name, childobj.className, 'CMg',childobj.CMg, 'KMg_A',childobj.KMg_A, 'KMg_B',childobj.KMg_B) elif classname in ['SpikeGen']: - childobj = _moose.SpikeGen(childid) + childobj = moose.SpikeGen(childid) print(spacefill+"|--", childobj.name, childobj.className, 'threshold',childobj.threshold) elif classname in ['Func']: - childobj = _moose.Func(childid) + childobj = moose.Func(childid) print(spacefill+"|--", childobj.name, childobj.className, 'expr',childobj.expr) elif classname in ['Table']: # Table gives segfault if printRecursiveTree is called on it return # so go no deeper @@ -831,15 +754,15 @@ def setup_vclamp(compartment, name, delay1, width1, level1, gain=0.5e-5): """ ## If /elec doesn't exists it creates /elec and returns a reference to it. ## If it does, it just returns its reference. - _moose.Neutral('/elec') - pulsegen = _moose.PulseGen('/elec/pulsegen'+name) - vclamp = _moose.DiffAmp('/elec/vclamp'+name) + moose.Neutral('/elec') + pulsegen = moose.PulseGen('/elec/pulsegen'+name) + vclamp = moose.DiffAmp('/elec/vclamp'+name) vclamp.saturation = 999.0 vclamp.gain = 1.0 - lowpass = _moose.RC('/elec/lowpass'+name) + lowpass = moose.RC('/elec/lowpass'+name) lowpass.R = 1.0 lowpass.C = 50e-6 # 50 microseconds tau - PID = _moose.PIDController('/elec/PID'+name) + PID = moose.PIDController('/elec/PID'+name) PID.gain = gain PID.tau_i = 20e-6 PID.tau_d = 5e-6 @@ -860,7 +783,7 @@ def setup_vclamp(compartment, name, delay1, width1, level1, gain=0.5e-5): pulsegen.secondLevel = -70e-3 pulsegen.secondWidth = 0.0 - vclamp_I = _moose.Table("/elec/vClampITable"+name) + vclamp_I = moose.Table("/elec/vClampITable"+name) vclamp_I.stepMode = TAB_BUF #TAB_BUF: table acts as a buffer. vclamp_I.connect("inputRequest", PID, "output") vclamp_I.useClock(PLOTCLOCK) @@ -875,9 +798,9 @@ def setup_iclamp(compartment, name, delay1, width1, level1): """ ## If /elec doesn't exists it creates /elec and returns a reference to it. ## If it does, it just returns its reference. - _moose.Neutral('/elec') - pulsegen = _moose.PulseGen('/elec/pulsegen'+name) - iclamp = _moose.DiffAmp('/elec/iclamp'+name) + moose.Neutral('/elec') + pulsegen = moose.PulseGen('/elec/pulsegen'+name) + iclamp = moose.DiffAmp('/elec/iclamp'+name) iclamp.saturation = 1e6 iclamp.gain = 1.0 pulsegen.trigMode = 0 # free run @@ -897,7 +820,7 @@ def get_matching_children(parent, names): with their names containing any of the strings in list 'names'. """ matchlist = [] for childID in parent.children: - child = _moose.Neutral(childID) + child = moose.Neutral(childID) for name in names: if name in child.name: matchlist.append(childID) @@ -917,11 +840,11 @@ def blockChannels(cell, channel_list): e.g. 'K' should block all K channels (ensure that you don't use capital K elsewhere in your channel name!) """ for compartmentid in cell.children: # compartments - comp = _moose.Compartment(compartmentid) + comp = moose.Compartment(compartmentid) for childid in comp.children: - child = _moose.Neutral(childid) + child = moose.Neutral(childid) if child.className in ['HHChannel', 'HHChannel2D']: - chan = _moose.HHChannel(childid) + chan = moose.HHChannel(childid) for channame in channel_list: if channame in chan.name: chan.Gbar = 0.0 @@ -929,7 +852,7 @@ def blockChannels(cell, channel_list): def get_child_Mstring(mooseobject,mstring): for child in mooseobject.children: if child.className=='Mstring' and child.name==mstring: - child = _moose.Mstring(child) + child = moose.Mstring(child) return child return None @@ -942,9 +865,9 @@ def connect_CaConc(compartment_list, temperature=None): for compartment in compartment_list: caconc = None for child in compartment.children: - neutralwrap = _moose.Neutral(child) + neutralwrap = moose.Neutral(child) if neutralwrap.className == 'CaConc': - caconc = _moose.CaConc(child) + caconc = moose.CaConc(child) break if caconc is not None: child = get_child_Mstring(caconc,'phi') @@ -958,46 +881,46 @@ def connect_CaConc(compartment_list, temperature=None): caconc.B = 1 / (2*FARADAY) / \ (math.pi*compartment.diameter*compartment.length * caconc.thick) for child in compartment.children: - neutralwrap = _moose.Neutral(child) + neutralwrap = moose.Neutral(child) if neutralwrap.className == 'HHChannel': - channel = _moose.HHChannel(child) + channel = moose.HHChannel(child) ## If child Mstring 'ion' is present and is Ca, connect channel current to caconc for childid in channel.children: # in async13, gates which have not been created still 'exist' # i.e. show up as a child, but cannot be wrapped. try: - child = _moose.element(childid) + child = moose.element(childid) if child.className=='Mstring': - child = _moose.Mstring(child) + child = moose.Mstring(child) if child.name=='ion': if child.value in ['Ca','ca']: - _moose.connect(channel,'IkOut',caconc,'current') + moose.connect(channel,'IkOut',caconc,'current') #print 'Connected IkOut of',channel.path,'to current of',caconc.path ## temperature is used only by Nernst part here... if child.name=='nernst_str': - nernst = _moose.Nernst(channel.path+'/nernst') + nernst = moose.Nernst(channel.path+'/nernst') nernst_params = child.value.split(',') nernst.Cout = float(nernst_params[0]) nernst.valence = float(nernst_params[1]) nernst.Temperature = temperature - _moose.connect(nernst,'Eout',channel,'setEk') - _moose.connect(caconc,'concOut',nernst,'ci') + moose.connect(nernst,'Eout',channel,'setEk') + moose.connect(caconc,'concOut',nernst,'ci') #print 'Connected Nernst',nernst.path except TypeError: pass if neutralwrap.className == 'HHChannel2D': - channel = _moose.HHChannel2D(child) + channel = moose.HHChannel2D(child) ## If child Mstring 'ionDependency' is present, connect caconc Ca conc to channel for childid in channel.children: # in async13, gates which have not been created still 'exist' # i.e. show up as a child, but cannot be wrapped. try: - child = _moose.element(childid) + child = moose.element(childid) if child.className=='Mstring' and child.name=='ionDependency': - child = _moose.Mstring(child) + child = moose.Mstring(child) if child.value in ['Ca','ca']: - _moose.connect(caconc,'concOut',channel,'concen') + moose.connect(caconc,'concOut',channel,'concen') #print 'Connected concOut of',caconc.path,'to concen of',channel.path except TypeError: pass @@ -1010,13 +933,13 @@ from io import StringIO as _sio class _TestMooseUtils(unittest.TestCase): def test_printtree(self): - s = _moose.Neutral('/cell') - soma = _moose.Neutral('%s/soma'% (s.path)) - d1 = _moose.Neutral('%s/d1'% (soma.path)) - d2 = _moose.Neutral('%s/d2'% (soma.path)) - d3 = _moose.Neutral('%s/d3'% (d1.path)) - d4 = _moose.Neutral('%s/d4'% (d1.path)) - d5 = _moose.Neutral('%s/d5'% (s.path)) + s = moose.Neutral('/cell') + soma = moose.Neutral('%s/soma'% (s.path)) + d1 = moose.Neutral('%s/d1'% (soma.path)) + d2 = moose.Neutral('%s/d2'% (soma.path)) + d3 = moose.Neutral('%s/d3'% (d1.path)) + d4 = moose.Neutral('%s/d4'% (d1.path)) + d5 = moose.Neutral('%s/d5'% (s.path)) orig_stdout = sys.stdout sys.stdout = _sio() printtree(s) @@ -1037,15 +960,15 @@ cell """ self.assertEqual(sys.stdout.getvalue(), expected) sys.stdout = _sio() - s1 = _moose.Neutral('cell1') - c1 = _moose.Neutral('%s/c1' % (s1.path)) - c2 = _moose.Neutral('%s/c2' % (c1.path)) - c3 = _moose.Neutral('%s/c3' % (c1.path)) - c4 = _moose.Neutral('%s/c4' % (c2.path)) - c5 = _moose.Neutral('%s/c5' % (c3.path)) - c6 = _moose.Neutral('%s/c6' % (c3.path)) - c7 = _moose.Neutral('%s/c7' % (c4.path)) - c8 = _moose.Neutral('%s/c8' % (c5.path)) + s1 = moose.Neutral('cell1') + c1 = moose.Neutral('%s/c1' % (s1.path)) + c2 = moose.Neutral('%s/c2' % (c1.path)) + c3 = moose.Neutral('%s/c3' % (c1.path)) + c4 = moose.Neutral('%s/c4' % (c2.path)) + c5 = moose.Neutral('%s/c5' % (c3.path)) + c6 = moose.Neutral('%s/c6' % (c3.path)) + c7 = moose.Neutral('%s/c7' % (c4.path)) + c8 = moose.Neutral('%s/c8' % (c5.path)) printtree(s1) expected1 = """ cell1 @@ -1077,18 +1000,18 @@ cell1 """ testid = 'test%s' % (uuid.uuid4()) - container = _moose.Neutral('/test') - model = _moose.Neuron('/test/%s' % (testid)) - soma = _moose.Compartment('%s/soma' % (model.path)) + container = moose.Neutral('/test') + model = moose.Neuron('/test/%s' % (testid)) + soma = moose.Compartment('%s/soma' % (model.path)) soma.diameter = 20e-6 soma.length = 0.0 parent = soma comps = [] for ii in range(100): - comp = _moose.Compartment('%s/comp_%d' % (model.path, ii)) + comp = moose.Compartment('%s/comp_%d' % (model.path, ii)) comp.diameter = 10e-6 comp.length = 100e-6 - _moose.connect(parent, 'raxial', comp, 'axial') + moose.connect(parent, 'raxial', comp, 'axial') comps.append(comp) parent = comp soma = autoposition(model) diff --git a/python/moose/verification_utils.py b/python/moose/verification_utils.py deleted file mode 100644 index 973c03f1..00000000 --- a/python/moose/verification_utils.py +++ /dev/null @@ -1,265 +0,0 @@ - - -"""verification_utils.py: - - IT contains a class which runs tests on moose internal data-structures to - check if it is good for simulation. - -Last modified: Sun Feb 15, 2015 12:21PM - -""" -from __future__ import print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import sys -import sys -from . import _moose as moose -import unittest -import inspect -from . import print_utils as debug -import numpy as np -from .backend import backend - - -class MooseTestCase( unittest.TestCase ): - - def dump(self, msg, end=''): - ''' Dump the messages in test functions ''' - caller = inspect.stack()[1][3] - if type(msg) == list: - msg = '\n\t|- '.join(msg) - print(('[VERIFY] {:80s}[{}]'.format(msg, caller))) - - def setUp(self): - '''Initialize storehouse - ''' - if not backend.moose_elems.filled: - backend.moose_elems.populateStoreHouse() - - self.mooseElems = backend.moose_elems - self.nonZeroClockIds = None - - def test_disconnected_compartments(self): - '''Test if any comparment is not connected ''' - self.dump("Checking if any compartment is not connected ...") - for c in self.mooseElems.compartments: - if (c.neighbors['axial'] or c.neighbors['raxial']): - continue - elif c.neighbors['injectMsg']: - continue - else: - msg = '%s is not connected with any other compartment' % c.path - debug.dump('FAIL' - , [ msg - , 'Did you forget to use `moose.connect`?' - ] - ) - - def test_isolated_pulse_gen(self): - ''' Test if any pulse-generator is not injecting current to a - compartment - ''' - self.dump('Checking if any pulse-generator is floating') - for pg in self.mooseElems.pulseGens: - if pg.neighbors['output']: - continue - else: - debug.dump( - 'FAIL' - , [ 'Current source {} is floating'.format(pg.path) - , 'It is not injecting current to any compartment' - , 'Perhaps you forgot to use `moose.connect`?' - ] - ) - - def test_synchans(self): - self.dump("Checking if any synapse is dead") - for synchan in self.mooseElems.synchans: - if synchan.Gbar <= 0.0: - debug.dump("WARN" - , [ synchan.path - , "Gbar value is zero or negative: %s" % synchan.Gbar - , "Not cool!" - ] - ) - # Check the output of synchan. - if not synchan.neighbors['channel']: - debug.dump("FAIL" - , [ "SynChan %s is not connected to post-compartment" % synchan.path - , " No connected 'channel'. " - " Did you forget to connect compartment e.g." - "moose.connect(synchan, 'channel', comp, 'channel')" - " where synchan is 'moose.SynChan' and comp is " - " 'moose.Compartment'?" - ] - ) - else: - pass - - # Check if anyone is activating this synchan. - synhandlers = synchan.neighbors['activation'] - if not synhandlers: - debug.dump("FAIL" - , [ "No SynHandler is activating SynChan %s" % synchan.path - , " Did you forget to connect a SynHandler e.g. " - "moose.connect(synHandler, 'activationOut', synchan, 'activation'" - " where synchan is 'moose.SynChan' and synHandler is" - " moose.SynHandler." - ] - ) - else: [self.test_synhandler(x) for x in synhandlers] - - def test_synhandler(self, synhandlers): - """A SynHandler object does not have incoming connections to itself. - Rather it keeps an array of moose.Synapse inside it which recieves input - of moose.SpikeGen. - """ - if type(synhandlers) == moose.vec: - if len(synhandlers) == 1: - synhandler = synhandlers[0] - else: - [self.test_synhandler(x) for x in synhandlers] - else: - synhandler = synhandlers - - for synapses in synhandler.synapse: - self.test_synapse(synapses) - - def test_synapse(self, synapses): - if type(synapses) == moose.Synapse: - synapse = synapses - elif type(synapses) == moose.vec: - if len(synapses) == 1: - synapse = synapses[0] - else: - [ self.test_synapse(x) for x in synapses ] - - spikeGens = synapse.neighbors['addSpike'] - if not spikeGens: - debug.dump('FAIL' - , [" Synapse %s has no incoming spikes" % synapse.path - , " Did you forget to connect a moose.SpikeGen e.g." - " moose.connect(spikegen, 'spikeOut', synapse, 'addSpike')" - ] - ) - else: - [self.test_spikegen(x) for x in spikeGens] - - def test_spikegen(self, spikegens): - spikeGen = None - if len(spikegens) > 1: - [self.test_spikegen(x) for x in spikegens] - elif len(spikegens) == 1: - spikeGen = spikegens[0] - elif type(spikegens) == moose.SpikeGen: - spikeGen = spikegens - - pre = spikeGen.neighbors['Vm'] - if not pre: - debug.dump('FAIL', - [ "SpikeGen %s is not reading Vm of any compartment " % spikeGen.path - , "Did you forget to connect Vm of a " - "compartment to this SpikeGen? " - " e.g. moose.connect(comp, 'VmOut', spikeGen, 'Vm')" - ] - ) - else: pass - - - def test_unused_tables(self): - '''Tests if any table is not reading data. Such tables remain empty. - ''' - self.dump('Checking if any table is not connected') - for table in self.mooseElems.tables: - if table.neighbors['requestOut']: - continue - else: - debug.dump( - 'FAIL' - , [ 'Table {} is not reading data.'.format(table.path) - , ' Did you forget to use `moose.connect`?' - ] - ) - - def test_clocks(self): - """Tests if clocks are missing. """ - self.dump("Checking if clocks are available") - try: - clock = self.mooseElems.clocks[0] - except: - debug.dump("WARN", "Could not find any clock") - return - clockDtList = clock.dts - if np.count_nonzero(clockDtList) < 1: - debug.dump("FATAL" - , [ "No clock is found with non-zero dt size. " - , "Did you forget to use `moose.setClock` function?" - , "Quitting..." - ] - ) - sys.exit(0) - else: - self.nonZeroClockIds = np.nonzero(self.mooseElems.clocks) - - def test_methods_sensitivity(self): - """Test if each compartment has process connected to a non-zero clock""" - self.dump("Checking for insensitive processes") - [ self.checkSentitivity( m, objs) - for m in ['process', 'init'] - for objs in [self.mooseElems.compartments] - ] - [self.checkSentitivity('process', objs) - for objs in [self.mooseElems.tables, self.mooseElems.pulseGens] - ] - - - def checkSentitivity( self, methodName, objectList): - """Check if a given method is sensitive to any non-zero clock - """ - assert type(methodName) == str - insensitiveObjectList = [] - for obj in objectList: - if not obj.neighbors[methodName]: - insensitiveObjectList.append(obj) - else: - # Here we must check if method is made sensitive to a - # zero-clock. Currently there is no way to test it in python. - pass - - if len(insensitiveObjectList) > 0: - msgList = [ - "Method `%s` is insensitive to all clocks. " % methodName - , "Total {} out of {} object ({}) fails this test".format( - len(insensitiveObjectList) - , len(objectList) - , type(insensitiveObjectList[0]) - ) - ] - debug.dump("FAIL", msgList) - -def verify( *args, **kwargs): - '''Verify the current moose setup. Emit errors and warnings - ''' - connectivitySuite = unittest.TestSuite() - connectivitySuite.addTest(MooseTestCase('test_disconnected_compartments')) - connectivitySuite.addTest(MooseTestCase('test_isolated_pulse_gen')) - connectivitySuite.addTest(MooseTestCase('test_unused_tables')) - connectivitySuite.addTest(MooseTestCase('test_synchans')) - - simulationSuite = unittest.TestSuite() - simulationSuite.addTest(MooseTestCase('test_clocks')) - simulationSuite.addTest(MooseTestCase('test_methods_sensitivity')) - - # We can replace self with run also and collect the result into a result - # object. - connectivitySuite.debug() - simulationSuite.debug() - diff --git a/tests/python/test_hsolve_externalCalcium.py b/tests/python/test_hsolve_externalCalcium.py index 92f5e68e..9519d863 100644 --- a/tests/python/test_hsolve_externalCalcium.py +++ b/tests/python/test_hsolve_externalCalcium.py @@ -4,11 +4,11 @@ import os import sys import numpy as np import time -import moose -import matplotlib.pyplot as plt import test_difshells as td import chan_proto import param_chan + +import moose print('Using moose from %s' % moose.__file__ ) difshell_no = 3 @@ -20,6 +20,13 @@ p_file = os.path.join( script_dir_, "soma.p" ) cond = {'CaL12':30*0.35e-5, 'SK':0.5*0.35e-6} +def assert_stat( vec, expected ): + min_, max_ = np.min( vec ), np.max( vec ) + mean, std = np.mean( vec ), np.std( vec ) + computed = [ min_, max_, mean, std ] + assert np.allclose( computed, expected ), \ + "Got %s expected %s" % (computed, expected) + if __name__ =='__main__': for tick in range(0, 7): moose.setClock(tick,10e-6) @@ -66,9 +73,10 @@ if __name__ =='__main__': t_stop = 10. moose.reinit() moose.start(t_stop) - print( sktab.vector ) - print( shelltab.vector ) - print(len(np.where(sktab.vector<1e-19)[0]), - len(np.where(shelltab.vector>50e-6)[0]) - ) + vec1 = sktab.vector + vec2 = shelltab.vector + assert_stat( vec1, [ 0.0, 5.102834e-22, 4.79066e-22, 2.08408e-23 ] ) + assert_stat( vec2, [ 5.0e-5, 5.075007e-5, 5.036985e-5, 2.1950117e-7] ) + assert len(np.where(sktab.vector<1e-19)[0]) == 2001 + assert len(np.where(shelltab.vector>50e-6)[0]) == 2000 -- GitLab