#!/usr/bin/python
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------
# Copyright (c) 2012 Michael Hull.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------
from Cheetah.Template import Template
from datetime import datetime
mod_tmpl_header = """
TITLE $title
COMMENT
Modfile Generated by morphforge:
###$__dict__
SUFFIX: $suffix
ENDCOMMENT
"""
mod_tmpl_units = """
UNITS {
#for ($uAbbr, $uName) in $units.iteritems():
($uAbbr) = ($uName)
#end for
}
"""
mod_tmpl_interface = """
? interface
NEURON {
THREADSAFE
SUFFIX $suffix
NONSPECIFIC_CURRENT $currentname
RANGE $rangevars
}
"""
mod_tmpl_params = """
PARAMETER {
#for $pName, ($pValue, $pUnit, $pRange) in $parameters.iteritems():
#set $pUnitOut = "("+pUnit+")" if $pUnit else ""
#set $pRangeOut = "<%1.1e, %1.1e>"%pRange if $pRange else ""
$pName = $pValue $pUnitOut $pRangeOut
#end for
}
"""
mod_tmpl_state = """
STATE {
#for state in $internalstates:
$state
#end for
#if $chlsopenequation:
chls_open
#end if
}
"""
mod_tmpl_assigned = """
ASSIGNED {
v (mV)
celsius (degC)
$currentname (mA/cm2)
#for $rName, ($rEqn, $rUnit) in $rates.iteritems():
#set $rUnitOut = "("+rUnit+")" if $rUnit else ""
$rName $rUnitOut
#end for
#if $conductanceequation:
g (S/cm2)
#end if
}
"""
mod_tmpl_breakpoints = """
? currents
BREAKPOINT {
#if $internalstates:
SOLVE states METHOD cnexp
#end if
$currentname = $currentequation
#if $conductanceequation:
g = $conductanceequation
#end if
#if $chlsopenequation:
chls_open = chlsopenequation
#end if
}
"""
mod_tmpl_initial = """
INITIAL {
${updatefunctionname}(v)
#for $state, ($initialvalue, $equation) in $internalstates.iteritems():
$state = $initialvalue
: MH TEMP HACK
$state = 0
#end for
}
"""
mod_tmpl_derivative = """
? states
DERIVATIVE states {
${updatefunctionname}(v)
#for $state, ($initialvalue, $equation) in $internalstates.iteritems():
$equation
#end for
}
"""
mod_tmpl_procedure = """
? rates
PROCEDURE ${updatefunctionname}(v(mV)) {
#set $locals = [r[0][0] for r in $rates.values() if r[0][0]]
#set $localString = "LOCAL " + ",".join($locals) if $locals else ""
$localString
UNITSOFF
#for $rName in $ratecalcorder:
#set (($rEqnLocals, $rEqn), $rUnit) = $rates[$rName]
$rEqn
#end for
}
"""
mod_tmpl_functions = """
$functions
UNITSON
"""
[docs]class MM_ModFileWriterBase(object):
_default_title = 'Untitled mod-file'
_default_comment = 'Automatically generated modfile - morphforge @ '
default_units = {
'mA': 'milliamp',
'mV': 'millivolt',
'S': 'siemens',
'pA': 'picoamp',
'um': 'micrometer',
}
_default_current_name = 'i'
defaultupdatefunctionname = 'rates'
[docs] def __init__(
self,
suffix,
title=None,
internalstates=None,
parameters=None,
functions=None,
rates=None,
ratecalcorder=None,
currentequation=None,
conductanceequation=None,
chlsopenequation=None,
units=None,
):
self.title = (title if title else self._default_title)
time_str = datetime.now().strftime('%A, %d. %B %Y %I:%M%p')
self.comment = self._default_comment + time_str
self.suffix = suffix
# {name: (initialvalue, equation) }
self.internalstates = (internalstates if internalstates else {})
# {name: (value, unit, range)}
self.parameters = (parameters if parameters else {})
# {name: ((locals, equnation), unit) }
self.rates = (rates if rates else {})
self.ratecalcorder = (ratecalcorder if ratecalcorder else [])
# {name: code}
self.functions = (functions if functions else '')
self.currentname = self._default_current_name
self.units = (units if units else self.default_units)
self.currentequation = currentequation
self.updatefunctionname = self.defaultupdatefunctionname
# Optional:
self.conductanceequation = conductanceequation
self.chlsopenequation = chlsopenequation
self.rangevars = None
[docs] def generate_modfile(self):
assert self.currentequation
self.rangevars = ','.join(self.parameters.keys()
+ self.rates.keys()
+ self.internalstates.keys() + ['i',
'g'])
if self.internalstates:
blks = [
mod_tmpl_header,
mod_tmpl_units,
mod_tmpl_interface,
mod_tmpl_params,
mod_tmpl_state,
mod_tmpl_assigned,
mod_tmpl_breakpoints,
mod_tmpl_initial,
mod_tmpl_derivative,
mod_tmpl_procedure,
mod_tmpl_functions,
]
elif self.conductanceequation:
blks = [
mod_tmpl_header,
mod_tmpl_units,
mod_tmpl_interface,
mod_tmpl_params,
mod_tmpl_state,
mod_tmpl_assigned,
mod_tmpl_breakpoints,
mod_tmpl_procedure,
mod_tmpl_functions,
]
else:
blks = [
mod_tmpl_header,
mod_tmpl_units,
mod_tmpl_interface,
mod_tmpl_params,
mod_tmpl_assigned,
mod_tmpl_breakpoints,
mod_tmpl_procedure,
mod_tmpl_functions,
]
# Debug:
# for blk in blks:
# print blk
# print Template(blk, [self]).respond()
resps = [Template(blk, [self]).respond() for blk in blks]
return ''.join(resps)