//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