//genesis
//
// $Id: xcell.g 1.1.1.6.1.5.2.6.1.1.2.1.2.2.1.2 Thu, 04 Apr 2002 12:35:02 +0200 hugo $
//
//////////////////////////////////////////////////////////////////////////////
//'
//' Purkinje tutorial
//'
//' (C) 1998-2002 BBF-UIA
//'
//' see our site at http://www.bbf.uia.ac.be/ for more information regarding
//' the Purkinje cell and genesis simulation software.
//'
//'
//' functional ideas ... Erik De Schutter, erik@bbf.uia.ac.be
//' genesis coding ..... Hugo Cornelis, hugo@bbf.uia.ac.be
//'
//' general feedback ... Reinoud Maex, Erik De Schutter
//'
//////////////////////////////////////////////////////////////////////////////
// xcell.g : xcell functionality
int include_xcell
if ( {include_xcell} == 0 )
include_xcell = 1
//////////////////////////////////////////////////////////////////////////////
//o
//o xcell library : future enhancements
//o -----------------------------------
//o
//o The main major idea for future enhancement is to have a library for xcell
//o displays where each display can have its own output mode.
//o
//o
//o 1. Requirements
//o ---------------
//o
//o Because the number of possible outputs is finite, the idea is to mirror
//o the output mode of an xcell display in its path.
//o
//o e.g.:
//o /xcells/Vm............: gives Vm output
//o /xcells/CaP/Ik........: gives Ik for CaP channel
//o /xcells/Cap/Gk........: gives Gk for CaP channel
//o /xcells/CaP/Ek........: gives Ek for CaP channel
//o . . . . . .
//o . . . . . .
//o
//o The xcell displays are created only when they are needed. This gives less
//o overhead at setup time (mainly because the messages don't have to be
//o created) and at run time (because each visible xcell display doesn't
//o have to go through an enormous amount of messages). Opportunity must
//o be given to delete/hide xcells. If necessary / possible the messages
//o should be deleted to increase performance. When an xcell display is
//o hidden, it should be disabled such that it doesn't receive any PROCESS
//o actions anymore.
//o
//o Graphs plotting the values associated with particular compartments are
//o different in there path hierarchy : One graph is created for each of
//o Ik,Gk,Ek and for Vm and [Ca2+]. Perhaps this can also give a nicer
//o name to the different plots (e.g. b1s14_16 instead of
//o b1s14_16_Ca_pool_Ca etc).
//o The link between the xcell displays and the plotting graphs is as
//o follows : if a click occures inside an xcell display, we ask the user
//o first which output parameter he wants, this defaults to the xcell's
//o display output parameter.
//o
//o Besides this we still have to provide a possibility to have a plot
//o without any xcell display where we can type the compartment name to
//o plot.
//o As with xcell displays, opportunity must be given to delete graphs.
//o If possible any messages should be deleted to increase performance.
//o
//o The config file/module should be able to reflect a particular situation.
//o This situation should then be created at initialization. To specify
//o this situation an enumeration of xcell displays and xgraphs is given
//o with their output parameters.
//o
//o e.g. :
//o
//o . . .
//o . . .
//o xCellElements 1600 (old values)
//o XCell Vm (creates /xcells/Vm)
//o XCell CaP Ik (creates /xcells/CaP/Ik)
//o XGraph CaP Ek (creates /xgraphs/CaP/Ek)
//o XGraph Vm soma[0] (creates /xgraphs/Vm plotting soma Vm)
//o . . .
//o . . .
//o
//o In the long run it should be possible to save such a configuration
//o from the tutorial itself (without having to run the configuration
//o script). Perhaps a seperate file for this configuration from which the
//o name is given in the config file is better. This lets one choose
//o between different output modes easily by changing the config file.
//o
//o At this moment I don't see any interference with the boundaries settings,
//o but I could be wrong on that.
//o
//o
//o 2. Implementation
//o -----------------
//o
//o A seperate library is needed asking for a particular output mode. Part of
//o this is present in the actual xcell code. The same applies for asking
//o the user for a particular compartment to plot. This code is partly
//o present in the xgraph code.
//o
//o
//////////////////////////////////////////////////////////////////////////////
//v bool to indicate first toggle for tabchannel has been created
int bButtonsCreated = 0
//v bool for communication between XCellAddElectrode and XCellCBAddPlot
int bXCellAddElectrodeResult = 0
//v basename for library file of all channels
str strXCLibrary = "XCLib"
///
/// SH: XCellElectrodeName
///
/// PA: path..: path to the clicked compartment
///
/// RE: name for electrode
///
/// DE: Associate an electrode name with {path} for registered xcell parameters
/// The electrode name will have a fairly descriptive name (ie from the
/// electrode name you can make out which field from which compartment is
/// recorded.
///
function XCellElectrodeName(path)
str path
//- get the registered xcell output source
str xcOutputSource = {getfield /xcell outputSource}
//- get the registered xcell output value
str xcOutputValue = {getfield /xcell outputValue}
//- get the registered xcell output flags
int xcOutputFlags = {getfield /xcell outputFlags}
//- get the electrode name
str electrode = {XGraphPlotTitle \
{path} \
{xcOutputSource} \
{xcOutputValue} \
{xcOutputFlags}}
//- return electrode name
return {electrode}
end
///
/// SH: XCellAddElectrode
///
/// PA: path..: path to the clicked compartment
/// name..: name for electrode
/// color.: color for the electrode
///
/// RE: 1 if successfull
/// 0 if failed (the electrode already exists)
///
/// DE: Associate an electrode with {path} for registered xcell parameters
///
/// Electrode prototype is /electrodes/draw/proto {xshape}
///
/// The electrode is created within
/// /electrodes/draw/{name}.......: always
/// /xcell/draw/{name}............: when electrodes visible
/// in xcell display
///
function XCellAddElectrode(path,name,color)
str path
str name
int color
//- set default result
int bResult = 0
//- give diagnostics
echo "Adding electrode for "{name}
//- copy the prototype electrode
copy /electrodes/draw/proto /electrodes/draw/{name}
//- set field for identification and color
setfield ^ \
ident "record" \
pixcolor {color}
//- set the translation of the electrode
setfield ^ \
tx {getfield {path} x} \
ty {getfield {path} y} \
tz {getfield {path} z}
//- if the electrodes toggle is set
if ( {getfield /xcell/electrodes state} )
//- copy the electrode to the xcell window
copy ^ /xcell/draw/{name}
end
//- set success
bResult = 1
//- set the result in a global
bXCellAddElectrodeResult = {bResult}
//- return result
return {bResult}
end
///
/// SH: XCellPrepareElectrodes
///
/// DE: Prepare electrodes
///
function XCellPrepareElectrodes
//- create a container
create xform /electrodes
//- disable the form
disable ^
//- create a draw
create xdraw /electrodes/draw
//- create an electrode prototype shape
create xshape /electrodes/draw/proto \
-linewidth 1 \
-textmode nodraw \
-pixcolor red \
-coords [-40e-7,0,90e-7][0,0,0][-20e-7,0,100e-7][-30e-7,0,95e-7][-40e-7,0,150e-7][-140e-7,0,100e-7]
//- add a field for identification
addfield ^ \
ident -description "Identification"
//- set the field
setfield ^ \
ident "prototype"
end
///
/// SH: XCellRemoveElectrode
///
/// PA: path..: path to the clicked compartment
///
/// DE: Remove the electrode associated with {path}
///
function XCellRemoveElectrode(path)
str path
//- get the registered xcell output source
str xcOutputSource = {getfield /xcell outputSource}
//- get the registered xcell output value
str xcOutputValue = {getfield /xcell outputValue}
//- get the registered xcell output flags
int xcOutputFlags = {getfield /xcell outputFlags}
//- get the electrode title
str plotTitle = {XGraphPlotTitle \
{path} \
{xcOutputSource} \
{xcOutputValue} \
{xcOutputFlags}}
//- if the electrode exists
if ( {exists /electrodes/draw/{plotTitle}} )
//- give diagnostics
echo "Removing electrode "{plotTitle}
//- remove the electrode
delete /electrodes/draw/{plotTitle}
//- if the electrodes toggle is set
if ( {getfield /xcell/electrodes state} )
//- delete the electrode from the xcell window
delete /xcell/draw/{plotTitle}
//- update the draw widget
//xflushevents
xupdate /xcell/draw
//! to get around a bug that does not update
//! the deleted electrodes :
//! hide and show the parent form
xhide /xcell
xshow /xcell
end
//- else
else
//- give diagnostics
echo "No electrode named "{plotTitle}
end
end
///
/// SH: XCellRemoveElectrodes
///
/// DE: Remove all electrodes
///
function XCellRemoveElectrodes
//- give diagnostics
echo "Removing all electrodes"
//- loop over all registered electrode
str electr
foreach electr ( {el /electrodes/draw/#[][ident=record]} )
//! because of a bug in the wildcard parsing
//! we can stil get the prototype here.
//! we must check this by name of the element
//- if it is not the prototype
if ( {getpath {electr} -tail} != "proto" )
//- delete the electrode to the xcell window
delete {electr}
end
end
//- update the state of the electrodes
callfunc XCellSetupElectrodes {getfield /xcell/electrodes state}
end
///
/// SH: XCellSetupElectrodes
///
/// PA: state.: 0 if electrodes should be invisible
/// 1 if electrodes should be visible
///
/// DE: Show/hide the electrodes
///
function XCellSetupElectrodes(state)
int state
//- loop over all electrodes in the xcell window
str electr
foreach electr ( {el /xcell/draw/#[][ident=record]} )
//- remove the electrode
delete {electr}
end
//- if the electrodes should be visible
if (state)
//- give diagnostics
echo "Showing electrodes"
//- loop over all registered electrode
foreach electr ( {el /electrodes/draw/#[][ident=record]} )
//- get the tail of the name
str tail = {getpath {electr} -tail}
//! because of a bug in the wildcard parsing
//! we can stil get the prototype here.
//! we must check this by name of the element
if ( {tail} != "proto" )
//- copy the electrode to the xcell window
copy {electr} /xcell/draw/{tail}
end
end
//- else
else
//- give diagnostics
echo "Hiding electrodes"
end
//- update the draw widget
xflushevents
xupdate /xcell/draw
//! to get around a bug that does not update the deleted electrodes :
//! hide and show the parent form
//! for some reason it is not necessary here, but it is above
//! (removal of electrodes).
// xhide /xcell
// xshow /xcell
end
///
/// SH: XCellSetupGraph
///
/// PA: state.: 0 if graph should be invisible
/// 1 if graph should be visible
///
/// DE: Show/hide the graph
///
function XCellSetupGraph(state)
int state
//- if the graph should be visible
if (state)
//- show the graph
xshow /xgraphs
//- else
else
//- hide the graph
xhide /xgraphs
end
end
///
/// SH: XCellSwitchChanMode
///
/// PA: state.: 0 for absolute chanmode (chanmode 4)
/// 1 for normalized chanmode (chanmode 5)
///
/// DE: Switch between normalized and absolute channel mode
/// Sets the solver in {cellpath}/solve in chanmode 4 or 5.
/// Sets the min/max color values for the xcell display
/// Notifies graph for new chanmode
///
function XCellSwitchChanMode(state)
int state
//- if state is not zero
if (state)
//- switch to chanmode 5
iChanMode = 5
setfield {cellpath}/solve \
chanmode {iChanMode}
//- else
else
//- switch to chanmode 4
iChanMode = 4
setfield {cellpath}/solve \
chanmode {iChanMode}
end
//- get name for boundary element
str bound = {BoundElementName \
{getfield /xcell outputSource} \
{getfield /xcell outputValue} \
{iChanMode}}
//- set field for boundaries
setfield /xcell \
boundElement {bound}
//- set new boundaries from element
callfunc XCellSetBoundaries {bound}
//- notify graph new chanmode
XGraphSwitchChanMode {state}
end
///
/// SH: XCellDeleteMessages
///
/// DE: Delete the messages from the xcell
/// If no messages are setup, none will be deleted and the function
/// will cleanly return.
///
function XCellDeleteMessages
//- count the number of incoming messages
int iCount = {getmsg /xcell/draw/xcell1 -incoming -count}
//- if the count is not zero
if (iCount)
//- retreive the number of elements from the config
int iElements = {getfield /config xCellElements}
//- loop for the number of elements / messages
int i
for (i = 0; i < iElements; i = i + 1)
//- delete the first message
deletemsg /xcell/draw/xcell1 {0} -incoming
end
end
end
///
/// SH: XCellSetupMessages
///
/// PA: source: message source in {cellpath}
/// value.: message value within {source}
///
/// DE: Setup the messages between the solver and xcell
/// The solver is assumed to be {cellpath}/solve .
///
function XCellSetupMessages(source,value)
str source
str value
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- give diagnostics
echo "Setting up messages to xcell for "{source}", "{value}
str element
//
// foreach element ( { el { wPath } } )
// if ( {exists {element}/{source}} )
// echo Exists : {element}/{source}
// else
// echo Non existent : {element}/{source}
// end
// break
// end
//- loop over all elements in the xcell object
str element
foreach element ( { el { wPath } } )
//- if the source elements exists
if ( {exists {element}/{source}} )
//echo Exists : {element}/{source}
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element}/{source} \
{value}}
//- else the element does not exist
else
//echo Non existent : {element}/{source}
//- add a dummy message
addmsg /config /xcell/draw/xcell1 COLOR z
end
end
//- set number of compartments in the xcell object
setfield /xcell/draw/xcell1 \
nfield {getfield /config xCellElements}
//- give diagnostics
echo "Messages to xcell ok."
end
///
/// SH: XCellSetupCompMessages
///
/// PA: source: message source in {cellpath} (not used)
/// value.: message value within {source}
///
/// DE: Setup the messages between the solver and xcell for compartments
/// The solver is assumed to be {cellpath}/solve .
///
function XCellSetupCompMessages(source,value)
str source
str value
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- give diagnostics
echo "Setting up messages to xcell for (compartments), "{value}
//- loop over all elements in the xcell object
str element
foreach element ( { el { wPath } } )
//- if the source elements exists
if ( {exists {element}} )
//echo Exists : {element}
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element} \
{value}}
//- else the element does not exist
else
//echo Non existent : {element}
//- add a dummy message
addmsg /config /xcell/draw/xcell1 COLOR z
end
end
//- set number of compartments in the xcell object
setfield /xcell/draw/xcell1 \
nfield {getfield /config xCellElements}
//- give diagnostics
echo "Messages to xcell ok."
end
///
/// SH: XCellSetupExcIGEMessages
///
/// PA: source: message source in {cellpath}
/// value.: message value within {source}
///
/// DE: Setup the messages between the solver and xcell
/// The solver is assumed to be {cellpath}/solve .
///
function XCellSetupExcIGEMessages(source,value)
str source
str value
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- give diagnostics
echo "Setting up messages to xcell for " \
{source}", "{value}
//- loop over all elements in the xcell object
str element
foreach element ( { el { wPath } } )
//- get the spine that gives messages to the element
str spine = {getmsg {element} -outgoing -destination 7}
//- get tail of spine
str spineTail = {getpath {spine} -tail}
//- get head of spine for use with solver's flat space
str spineHead = {getpath {spine} -head}
//- if we are handling a spine
if ( {strncmp {spineTail} "spine" 5} == 0 )
//- default index is zero
source = "head[0]/par"
//- if an index is available
if ( {strlen {spineTail}} != 5 )
//- get index of synapse
int synapseIndex \
= {substring \
{spineTail} \
6 \
{{strlen {spineTail}} - 1}}
//- make source string with index
source = "head[" @ {synapseIndex} @ "]/par"
end
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{spineHead}{source} \
{value}}
//- else if we can find a climbing fiber input
elif ( {exists {element}/climb } )
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element}/climb \
{value}}
//- else the element does not exist
else
//- add a dummy message
addmsg /config /xcell/draw/xcell1 COLOR z
end
end
//- set number of compartments in the xcell object
setfield /xcell/draw/xcell1 \
nfield {getfield /config xCellElements}
//- give diagnostics
echo "Messages to xcell ok."
end
///
/// SH: XCellSetupInhIGEMessages
///
/// PA: source: message source in {cellpath}
/// value.: message value within {source}
///
/// DE: Setup the messages between the solver and xcell
/// The solver is assumed to be {cellpath}/solve .
///
function XCellSetupInhIGEMessages(source,value)
str source
str value
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- give diagnostics
echo "Setting up messages to xcell for " \
{source}", "{value}
//- loop over all elements in the xcell object
str element
foreach element ( { el { wPath } } )
//- if we are handling a stellate cell
if ( {exists {element}/stell} )
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element}/stell \
{value}}
//- else if we can find a stellate 1 cell
elif ( {exists {element}/stell1 } )
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element}/stell1 \
{value}}
//- else if we can find a basket cell
elif ( {exists {element}/basket } )
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{element}/basket \
{value}}
//- else no inhibitory channel exists
else
//- add a dummy message
addmsg /config /xcell/draw/xcell1 COLOR z
end
end
//- set number of compartments in the xcell object
setfield /xcell/draw/xcell1 \
nfield {getfield /config xCellElements}
//- give diagnostics
echo "Messages to xcell ok."
end
///
/// SH: XCellSetupSpineVmMessages
///
/// PA: source: message source in {cellpath}
/// value.: message value within {source}
///
/// DE: Setup the messages between the solver and xcell
/// The solver is assumed to be {cellpath}/solve .
///
function XCellSetupSpineVmMessages(source,value)
str source
str value
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- give diagnostics
echo "Setting up spine compartment messages to xcell for " \
{source}", "{value}
//- loop over all elements in the xcell object
str element
foreach element ( { el { wPath } } )
//- get the spine that gives messages to the element
str spine = {getmsg {element} -outgoing -destination 7}
//- get tail of spine
str spineTail = {getpath {spine} -tail}
//- get head of spine for use with solver's flat space
str spineHead = {getpath {spine} -head}
//- if we are handling a spine
if ( {strncmp {spineTail} "spine" 5} == 0 )
//- default index is zero
source = "head[0]"
//- if an index is available
if ( {strlen {spineTail}} != 5 )
//- get index of synapse
int synapseIndex \
= {substring \
{spineTail} \
6 \
{{strlen {spineTail}} - 1}}
//- make source string with index
source = "head[" @ {synapseIndex} @ "]"
end
//echo {spineHead}{source} {value}
//- find solve field and add the message
addmsg {cellpath}/solve /xcell/draw/xcell1 \
COLOR {findsolvefield \
{cellpath}/solve \
{spineHead}{source} \
{value}}
//- else the element does not exist
else
//- add a dummy message
addmsg /config /xcell/draw/xcell1 COLOR z
end
end
//- set number of compartments in the xcell object
setfield /xcell/draw/xcell1 \
nfield {getfield /config xCellElements}
//- give diagnostics
echo "Messages to xcell ok."
end
///
/// SH: XCellSetupButtons
///
/// PA: widget: name of toggled widget
/// mode..: output mode of xcell
/// 1 comp. Vm
/// 2 channel with IGE
/// 3 excitatory channel with IGE
/// 4 spine comp. Vm
/// 5 nernst E
/// 6 Calcium concen Ca
/// 7 inhibitory channel with IGE
///
/// DE: Display the buttons according to the output mode
///
function XCellSetupButtons(widget,mode)
str widget
int mode
//echo setupbuttons : {widget} {mode}
//- set the heading for the xcell form
setfield /xcell/heading \
title {getfield /xcell outputDescription}
//- comp. Vm
//- or spine comp. Vm
//- or nernst E
//- or Calcium concen Ca
if (mode == 1 || mode == 4 || mode == 5 || mode == 6)
//- hide I,G toggles
xhide /xcell/Ik
xhide /xcell/Gk
//- show I,G labels
xshow /xcell/noIk
xshow /xcell/noGk
//- show E label
xhide /xcell/Ek
xshow /xcell/noEk
//- channel with IGE
//- or excitatory channel with IGE
//- or inhibitory channel with IGE
elif (mode == 2 || mode == 3 || mode == 7)
//- hide I,G labels
xhide /xcell/noIk
xhide /xcell/noGk
//- show I,G toggles
xshow /xcell/Ik
xshow /xcell/Gk
//- get widget tail
str channel = {getpath {widget} -tail}
//- for a calcium channel
if ( {channel} == "CaP" || {channel} == "CaT")
//- show Ek toggle
xhide /xcell/noEk
xshow /xcell/Ek
//- else
else
//- hide Ek toggle
xshow /xcell/noEk
xhide /xcell/Ek
end
//- else there is something wrong
else
//- give diagnostics
echo "XCellSetupButtons : Wrong output mode for XCell"
end
//- loop over all toggle buttons in the xcell
str toggle
foreach toggle ( {el /xcell/#[][TYPE=xtoggle]} )
//- isolate the tail
str toggleTail = {getpath {toggle} -tail}
//- if the toggle is not for graph,
//- electrodes or abs/norm output
if (toggleTail != "graph" \
&& toggleTail != "electrodes" \
&& toggleTail != "chanmode")
//- unset the toggle
setfield {toggle} \
state 0
end
end
//- set the toggle that has been pressed
setfield {widget} \
state 1
//- set the toggle for the channel mode
setfield /xcell/{getfield /xcell channelMode} \
state 1
end
///
/// SH: XCellSetOutput
///
/// PA: widget: name of toggled widget
///
/// RE: output mode
/// 1 comp. Vm
/// 2 channel with IGE
/// 3 excitatory channel with IGE
/// 4 spine comp. Vm
/// 5 nernst E
/// 6 Calcium concen Ca
/// 7 inhibitory channel with IGE
///
/// DE: Setup messages for update of xcell, setup buttons, do a reset
///
function XCellSetOutput(widget)
str widget
//- set the field for output
setfield /xcell \
output {widget}
//- delete all messages from the xcell
XCellDeleteMessages
//- default we should not continue
int bContinue = 0
//v strings for construction of messages
str msgSource
str msgValue
str msgDescription
//= mode for setting up buttons
//=
//= 1 comp. Vm
//= 2 channel with IGE
//= 3 excitatory channel with IGE
//= 4 spine comp. Vm
//= 5 nernst E
//= 6 Calcium concen Ca
//= 7 inhibitory channel with IGE
int flButtons = 0
//- get the parameter attribute for the widget
str parameters = {getfield {widget} parameters}
//- if we are dealing with compartments
if (parameters == "Vm")
//- the description is compartmental voltage
msgDescription = "Compartmental voltage"
//- the source is empty
msgSource = ""
//- the value is Vm
msgValue = "Vm"
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 1
//- if we are dealing with spine compartments
elif (parameters == "spineVm")
//- the description is spiny voltage
msgDescription = "Spiny voltage"
//- the source is the head of the spine
msgSource = "head"
//- the value is Vm
msgValue = "Vm"
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 4
//- if we are dealing with nernst
elif (parameters == "E")
//- the description is Nernst
msgDescription = "Nernst"
//- the source is Ca_nernst
msgSource = "Ca_nernst"
//- the value is E
msgValue = "E"
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 5
//- if we are dealing with concentration
elif (parameters == "Ca")
//- the description is compartmental Ca conc.
msgDescription = "Compartmental [Ca2+]"
//- the source is Ca_pool
msgSource = "Ca_pool"
//- the value is Ca
msgValue = "Ca"
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 6
//- if we are dealing with channels
elif (parameters == "IGE")
//- the description is the channel with registered mode
msgDescription \
= {getpath {widget} -tail} \
@ " " \
@ {getfield \
/xcell/{getfield /xcell channelMode} \
description}
//- the source is slash + the widget tail
msgSource = {getpath {widget} -tail}
//- the value is registered in /xcell
msgValue = {getfield /xcell channelMode}
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 2
//- if we are dealing with exc channels
elif (parameters == "excIGE")
//- the description is the channel with registered mode
msgDescription \
= "Excitatory " \
@ {getfield \
/xcell/{getfield /xcell channelMode} \
description}
//- the source is not relevant
msgSource = "excitatory"
//- the value is registered in /xcell
msgValue = {getfield /xcell channelMode}
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 3
//- if we are dealing with inh channels
elif (parameters == "inhIGE")
//- the description is the channel with registered mode
msgDescription \
= "Inhibitory " \
@ {getfield \
/xcell/{getfield /xcell channelMode} \
description}
//- the source is not relevant
msgSource = "inhibitory"
//- the value is registered in /xcell
msgValue = {getfield /xcell channelMode}
//- remember to continue
bContinue = 1
//- set flags for buttons
flButtons = 7
//- else somebody messed up the code
else
//- give diagnostics
echo "Somebody messed up the code"
echo "XCell module bug"
end
//- if we should continue
if (bContinue)
//- if we are handling compartments
if (flButtons == 1)
//- setup messages for compartments
XCellSetupCompMessages {msgSource} {msgValue}
//- else if we are handling spine compartments
elif (flButtons == 4)
//- setup messages for spines
XCellSetupSpineVmMessages {msgSource} {msgValue}
//- else if we are handling exc channels
elif (flButtons == 3)
//- setup messages for those channels
XCellSetupExcIGEMessages {msgSource} {msgValue}
//- else if we are handling inh channels
elif (flButtons == 7)
//- setup messages for those channels
XCellSetupInhIGEMessages {msgSource} {msgValue}
//- else we are handling normal messages
else
//- setup messages
XCellSetupMessages {msgSource} {msgValue}
end
end
//- register output description
setfield /xcell \
outputDescription {msgDescription}
//- set up buttons correctly
XCellSetupButtons {widget} {flButtons}
//- get name of boundary element
str bound = {BoundElementName {msgSource} {msgValue} {iChanMode}}
//- register the output parameters and boundary element
setfield /xcell \
outputSource {msgSource} \
outputValue {msgValue} \
outputFlags {flButtons} \
outputDescription {msgDescription} \
boundElement {bound}
//- set boundaries for xcell
callfunc XCellSetBoundaries {bound}
//- reset the simulation
reset
//- notify graph of switched output units
callfunc XGraphNextPlotMode {msgValue}
//- return the output mode
return {flButtons}
end
///
/// SH: XCellSetBoundaries
///
/// PA: bound.: boundary element
///
/// RE: Success of operation
///
/// DE: Set boundaries from the given element, update color widgets
///
function XCellSetBoundaries(bound)
str bound
//v result var
int bResult
//- if the element with the boundaries exists
if ( {exists {bound}} )
//- give diagnostics
echo "Setting xcell color boundaries from "{bound}
//- set the fields for dimensions
setfield /xcell/draw/xcell1 \
colmin {getfield {bound} xcellmin} \
colmax {getfield {bound} xcellmax}
//- set config values in color widgets
callfunc XCellShowConfigure
//- set result : ok
bResult = 1
//- else
else
//- set result : failure
bResult = 0
end
//- return result
return {bResult}
end
///
/// SH: XCellSetChannelMode
///
/// PA: widget: name of toggled widget
///
/// DE: Set the channel mode
///
function XCellSetChannelMode(widget)
str widget
//- isolate the tail of the toggled widget
str widgetTail = {getpath {widget} -tail}
//- set the channelmode field
setfield /xcell \
channelMode {widgetTail}
//- update the output messages
XCellSetOutput {getfield /xcell output}
end
///
/// SH: XCellCancelConfigure
///
/// DE: Hide the configure window
///
function XCellCancelConfigure
//- hide the configure window
xhide /xcell/configure
end
///
/// SH: XCellSetConfigure
///
/// DE: Set xcell config as in the configuration window
///
function XCellSetConfigure
//- set color min
setfield /xcell/draw/xcell1 \
colmin {getfield /xcell/colormin value}
//- set color max
setfield /xcell/draw/xcell1 \
colmax {getfield /xcell/colormax value}
end
///
/// SH: XCellShowConfigure
///
/// DE: Show configuration window for xcell
///
function XCellShowConfigure
//- set color min value
setfield /xcell/colormin \
value {getfield /xcell/draw/xcell1 colmin}
//- set color max value
setfield /xcell/colormax \
value {getfield /xcell/draw/xcell1 colmax}
/*
//- pop up the configuration window
xshow /xcell/configure
*/
end
///
/// SH: XCellCreateToggle
///
/// PA: name..: name of widget to create
///
/// DE: Create a channel toggle button in the xcell form.
/// The button is only created if it does not exist yet.
///
function XCellCreateToggle(name)
str name
//- if the widget does not exist yet
if ( ! {exists /xcell/{name}} )
//- if there are already channels created
if (bButtonsCreated)
//- create a toggle button beneath previous
create xtoggle /xcell/{name} \
-xgeom 90% \
-wgeom 10% \
-script "XCellSetOutput <w>"
//- else
else
//- create toggle button at upper right
create xtoggle /xcell/{name} \
-xgeom 90% \
-ygeom 5% \
-wgeom 10% \
-script "XCellSetOutput <w>"
//- remember that buttons are created
bButtonsCreated = 1
end
//- add field for parameters
addfield ^ \
parameters -description "parameters for messages"
//- set the parameter field to channels
setfield ^ \
parameters "IGE"
end
end
///
/// SH: XCellCreateChannelLibrary
///
/// DE: Create library of Purkinje channels in /library
///
function XCellCreateChannelLibrary
//v number of channels
int iChannels = 0
//- create neutral container
create neutral /tmp
//- loop over all purkinje channels found in the library
str channel
foreach channel ( {el /library/Purk_#/#[][TYPE=tabchannel]} )
//- isolate the name of the channel
str tail = {getpath {channel} -tail}
//- if the element does not exist
if ( ! {exists /tmp/{tail}} )
//- create library element
create neutral /tmp/{tail}
//- increment number of channels
iChannels = {iChannels + 1}
end
end
//- open the library file
openfile {strXCLibrary}".u" w
//- loop over all create elements
foreach channel ( {el /tmp/#[]} )
//- write tail of channel to the lib file
writefile {strXCLibrary}".u" {getpath {channel} -tail}
//- delete the neutral element
delete {channel}
end
//- close the lib file
closefile {strXCLibrary}".u"
//- sort the lib file
sh "sort <"{strXCLibrary}".u >"{strXCLibrary}".s"
//- open the library file
openfile {strXCLibrary}".s" r
//- loop over all channels
int i
for (i = 0; i < iChannels; i = i + 1)
//- read a channel
channel = {readfile {strXCLibrary}".s" -linemode}
//- create a neutral element
create neutral /tmp/{channel}
end
//- close the lib file
closefile {strXCLibrary}".s"
end
///
/// SH: XCellCreateButtons
///
/// DE: Create the xcell buttons and toggles.
/// Looks at the library to check which tabchannels are present
///
function XCellCreateButtons
//- create toggle buttons per compartment
create xtoggle /xcell/comp \
-xgeom 70% \
-ygeom 5% \
-wgeom 20% \
-title "Comp. Vm" \
-script "XCellSetOutput <w>"
addfield ^ \
parameters -description "parameters for messages"
setfield ^ \
parameters "Vm"
create xtoggle /xcell/Caconcen \
-title "Comp. Ca" \
-xgeom 70% \
-wgeom 20% \
-script "XCellSetOutput <w>"
addfield ^ \
parameters -description "parameters for messages"
setfield ^ \
parameters "Ca"
create xtoggle /xcell/channelSpines \
-xgeom 70% \
-wgeom 20% \
-title "Exc. chan." \
-script "XCellSetOutput <w>"
addfield ^ \
parameters -description "parameters for messages"
setfield ^ \
parameters "excIGE"
create xtoggle /xcell/channelSpinesInh \
-xgeom 70% \
-wgeom 20% \
-title "Inh. chan." \
-script "XCellSetOutput <w>"
addfield ^ \
parameters -description "parameters for messages"
setfield ^ \
parameters "inhIGE"
// create xtoggle /xcell/compSpines \
// -xgeom 70% \
// -wgeom 20% \
// -title "Spine comp." \
// -script "XCellSetOutput <w>"
// addfield ^ \
// parameters -description "parameters for messages"
// setfield ^ \
// parameters "spineVm"
// create xtoggle /xcell/nernst \
// -xgeom 70% \
// -wgeom 20% \
// -script "XCellSetOutput <w>"
// addfield ^ \
// parameters -description "parameters for messages"
// setfield ^ \
// parameters "E"
//- create a label as seperator
create xlabel /xcell/sep1 \
-xgeom 70% \
-ygeom 3:last.bottom \
-wgeom 20% \
-title ""
//- create toggle buttons for Ik,Gk,Ek
create xtoggle /xcell/Ik \
-xgeom 70% \
-ygeom 1:sep1 \
-wgeom 20% \
-script "XCellSetChannelMode <w>"
create xtoggle /xcell/Gk \
-xgeom 70% \
-wgeom 20% \
-script "XCellSetChannelMode <w>"
create xtoggle /xcell/Ek \
-xgeom 70% \
-wgeom 20% \
-script "XCellSetChannelMode <w>"
//- add descriptions
addfield /xcell/Ik \
description -description "Description of output"
addfield /xcell/Gk \
description -description "Description of output"
addfield /xcell/Ek \
description -description "Description of output"
//- set descriptions
setfield /xcell/Ik \
description "current"
setfield /xcell/Gk \
description "conductance"
setfield /xcell/Ek \
description "reversal potential"
create xlabel /xcell/noIk \
-xgeom 70% \
-ygeom 4:sep1 \
-wgeom 20% \
-title "No Ik"
create xlabel /xcell/noGk \
-xgeom 70% \
-ygeom 3:last.bottom \
-wgeom 20% \
-title "No Gk"
create xlabel /xcell/noEk \
-xgeom 70% \
-ygeom 3:last.bottom \
-wgeom 20% \
-title "No Ek"
//- create a library of all channels
XCellCreateChannelLibrary
//- loop over all purkinje channels found in the library
str channel
foreach channel ( {el /tmp/#[]} )
//- isolate the name of the channel
str tail = {getpath {channel} -tail}
//- create a toggle if necessary
XCellCreateToggle {tail}
end
/*
//- create a label as seperator
create xlabel /xcell/sep2 \
-xgeom 70% \
-ygeom 3:Ek \
-wgeom 20% \
-title ""
*/
//- create toggle to show graph
create xtoggle /xcell/graph \
-xgeom 70% \
-ygeom 6:draw.bottom \
-wgeom 30% \
-title "" \
-onlabel "Graph" \
-offlabel "No Graph" \
-script "XCellSetupGraph <v>"
//- create toggle to show recording electrodes
create xtoggle /xcell/electrodes \
-xgeom 70% \
-ygeom 4:last.bottom \
-wgeom 30% \
-title "" \
-onlabel "Electrodes" \
-offlabel "No Electrodes" \
-script "XCellSetupElectrodes <v>"
//- create label as seperator
create xlabel /xcell/sep3 \
-xgeom 70% \
-ygeom 6:graph.top \
-wgeom 30% \
-title ""
//- create toggle to change normalized / absolute output
create xtoggle /xcell/chanmode \
-xgeom 70% \
-ygeom 6:last.top \
-wgeom 30% \
-title "" \
-onlabel "Normalized" \
-offlabel "Absolute" \
-script "XCellSwitchChanMode <v>"
//- create label with normalized / absolute description
create xlabel /xcell/chanlabel \
-xgeom 70% \
-ygeom 6:chanmode.top \
-wgeom 30% \
-title "Output mode :"
/*
//- create a label as seperator
create xbutton /xcell/config \
-xgeom 70% \
-wgeom 30% \
-title "Configure" \
-script "XCellShowConfigure"
*/
end
///
/// SH: XCellCreateColorDialogs
///
/// DE: Create the xcell color dialogs at the bottom
///
function XCellCreateColorDialogs
//- create color min dialog
create xdialog /xcell/colormax \
-xgeom 0:parent.left \
-ygeom 5:draw.bottom \
-wgeom 70% \
-title "Color maximum (red) : " \
-script "XCellSetConfigure"
//- create color max dialog
create xdialog /xcell/colormin \
-xgeom 0:parent.left \
-ygeom 0:last.bottom \
-wgeom 70% \
-title "Color minimum (blue) : " \
-script "XCellSetConfigure"
end
///
/// SH: XCellCreateHeadings
///
/// DE: Create the xcell headings for the draw and buttons
///
function XCellCreateHeadings
//- create header label
create xlabel /xcell/heading [0,0,70%,5%] \
-title "Comp. voltage"
//- create buttons label
create xlabel /xcell/outputs \
-xgeom 0:last.right \
-ygeom 0 \
-wgeom 30% \
-hgeom 5% \
-title "Possible outputs"
end
///
/// SH: XCellCreateDraw
///
/// DE: Create the xcell draw
///
function XCellCreateDraw
//- create draw within form
create xdraw /xcell/draw [0,5%,70%,80%] \
-wx 2e-3 \
-wy 2e-3 \
-transform ortho3d \
-bg white
//- set dimensions for draw
setfield /xcell/draw \
xmin -1.5e-4 \
xmax 1.5e-4 \
ymin -0.4e-4 \
ymax 3.1e-4
//- set projection mode
setfield /xcell/draw \
transform y
//- retreive the wildcard from the config file
str wPath = {getfield /config xCellPath}
//- create cell display
create xcell /xcell/draw/xcell1 \
-path {wPath} \
-colmin -0.09 \
-colmax 0.02 \
-diarange -20
//- set clock to use
useclock /xcell/draw/xcell1 9
end
///
/// SH: XCellReset
///
/// DE: Set the default state for the xcell
///
function XCellReset
//- default output is compartmental Vm
setfield /xcell \
output "/xcell/comp"
//- default channel mode is conductance
setfield /xcell \
channelMode "Gk"
//- if chanmode is 5
if (iChanMode == 5)
//- set widget to normalized output
setfield /xcell/chanmode \
state 1
//- else
else
//- set widget to absolute output
setfield /xcell/chanmode \
state 0
end
//- default : graph is not visible
setfield /xcell/graph \
state 0
//- default : electrodes are not visible
setfield /xcell/electrodes \
state 0
//- update all output (buttons, colors)
//! this just simulates a click on the comp. volt. button
XCellSetOutput {getfield /xcell output}
end
///
/// SH: XCellCBAddPlot
///
/// PA: path..: path to the clicked compartment
///
/// DE: Callback to add compartment to graph
///
function XCellCBAddPlot(path)
str path
//echo "XCellCBAddPlot : "{path}
//- allocate next color
callfunc "XGraphNextColor"
//! the field cNextColor should be considered private,
//! but read the comments below to understand why I had to
//! read it as if it is public.
//!
//! With this public read it becomes more difficult to decide if the
//! graph should do a reset (and skipping back to the default color)
//! Modularity with genesis scripts can be tough...
//- get allocated color
int color = {getfield /xgraphs/graph cNextColor}
//! genesis callfunc cannot handle strings nor can it handle ints
//! so the return value gets lost for the if statement
//- get name of electrode
str electrode = {XCellElectrodeName {path}}
//- if the electrode exists
if ( {exists /electrodes/draw/{electrode}} )
//- give diagnostics
echo {electrode}" is already a recording site"
//- else
else
//- add plot for clicked compartment
callfunc "XGraphPlotCompartment" /Purkinje {path} {color}
if ( {bXGraphPlotCompartmentResult} )
//- add electrode for the compartment
XCellAddElectrode {path} {electrode} {color}
end
end
end
///
/// SH: XCellCBRemovePlot
///
/// PA: path..: path to the clicked compartment
///
/// DE: Callback to remove compartment from graph
///
function XCellCBRemovePlot(path)
str path
//- remove the electrode
callfunc XCellRemoveElectrode {path}
//- remove plot from the clicked compartment
callfunc "XGraphRemoveCompartment" /Purkinje {path}
end
///
/// SH: XCellCreate
///
/// DE: Create the xcell display widget with all buttons
/// set the update clock to clock 9
///
function XCellCreate
//- create form container
create xform /xcell [0, 0, 500, 470]
//- add field for output
addfield /xcell \
output -description "Output (toggled widget)"
//- add field for output source
addfield /xcell \
outputSource -description \
"Output source (compartment subelement)"
//- add field for output value
addfield /xcell \
outputValue -description "Output value (Vm, Ik, Gk, Ek, Ca)"
//- add field for output flags
addfield /xcell \
outputFlags -description "Output flags (1-7)"
//- add field for output description
addfield /xcell \
outputDescription -description "Output description (Title)"
//- add field for channel mode
addfield /xcell \
channelMode -description "Channel display mode (Ik, Gk, Ek)"
//- add field for registering boundary element
addfield /xcell \
boundElement -description "Element with display boundaries"
//- create the heading at the top
XCellCreateHeadings
//- create the draw
XCellCreateDraw
//- create color dialog widgets at the bottom
XCellCreateColorDialogs
//- create the buttons and toggles
XCellCreateButtons
//- prepare the electrodes
XCellPrepareElectrodes
/*
// create a form for configuration
create xform /xcell/configure [250,250,300,150]
// make it the current element
pushe /xcell/configure
// create label with header
create xlabel heading \
-label "Color configuration"
// create color min dialog
create xdialog colormin \
-title "Color minimum : "
// create color max dialog
create xdialog colormax \
-title "Color maximum : "
// create done button
create xbutton done \
-title "Done" \
-script "XCellSetConfigure"
// create cancel button
create xbutton cancel \
-title "Cancel" \
-script "XCellCancelConfigure"
// pop previous element
pope
*/
// link the xcell and the graph for button clicks
/*
setfield /xcell/draw/xcell1 \
script "XCellCBAddPlot.d1 <v> ; XCellCBRemovePlot.d3 <v>"
*/
setfield /xcell/draw/xcell1 \
script "XCellCBRemovePlot.d3 <v>"
//- show the output form
xshow /xcell
end
end