// ----------------------------------------------------------------------------------- // Authors: Ronald van Elburg // // Purpose: Overcoming the need to write code to implement standard for loops // for parameter space exploration, generating output files and defining // protocols. // // History, Background, Related Papers: // // Other Files Needed: // OutputHandlers (new Handlers should be added to MRC_OutParamHandlerContainer): // MRC_TimeSeriesHandler.hoc // MRC_SpikeTrainHandler.hoc // MRC_ScalarHandler.hoc // // It is assumed that this file is loaded from MultipleRunControl.hoc which will load: // MRC_all_in_list.hoc defines an iterator for lists // nrngui.hoc standard GUI components // // // // Output: outputfiles defined by users // initial version: Matlab // // normal session files support // // Required Mechanisms: // // Warnings: // // Initial Creation Date: 2005-11-01 // ChangeNo Date ChangedBy Description of Changes // // ----------------------------------------------------------------------------------// if(name_declared("cvode")==0){ dialog_outcome= boolean_dialog("CVode not loaded, cannot continue! ","Quit","Continue Anyway") if(1==dialog_outcome){ quit() } } // These functions need to be defined for MRC to work properly, but to allow for easy overwriting them we first check if they are not defined already. isDefined=name_declared("MRC_Run") if(isDefined!=1){ execute1("proc MRC_Run(){run()}") } isDefined=name_declared("MRC_PrepareModel") if(isDefined!=1){ execute1("proc MRC_PrepareModel(){}") } begintemplate MRC_LoopParameter public name, displaytext, use public set, get,get_sessionstr public toggle strdef name, displaytext, tstr proc init() { if(0!=numarg()){ lower_limit=0 upper_limit=0 stepsize=0 use=1 name=$s1 setdisplaytext() } } proc set() { lower_limit=$1 upper_limit=$2 stepsize=$3 if(numarg()>3){ use=$4%2 } setdisplaytext() } proc get() { $&1=lower_limit $&2=upper_limit $&3=stepsize if(numarg()>3){ $&4=use } } proc setdisplaytext(){ if (use) { sprint(displaytext,"+ %s %g %g %g", name, lower_limit, upper_limit, stepsize) }else{ sprint(displaytext,"- %s %g %g %g", name, lower_limit, upper_limit, stepsize) } } proc toggle() { use = (use+1)%2 setdisplaytext() } proc get_sessionstr(){ // Because there is no way of knowing whether a block is open or closed we adopted the convention that // get_sessionstr only returns closed blocks and we make the calling code responsible for closing and // opening blocks before and after the current blocks. $s1="" sprint(tstr,"{tobj=new MRC_LoopParameter()}") $o2.save(tstr) sprint(tstr,"\t{object_push(tobj)}") $o2.save(tstr) sprint(tstr,"\t{") $o2.save(tstr) sprint(tstr,"\t\tname=\"%s\"",name) $o2.save(tstr) sprint(tstr,"\t\tlower_limit=%g",lower_limit) $o2.save(tstr) sprint(tstr,"\t\tupper_limit=%g",upper_limit) $o2.save(tstr) sprint(tstr,"\t\tstepsize=%g",stepsize) $o2.save(tstr) sprint(tstr,"\t\tuse=%d",use) $o2.save(tstr) sprint(tstr,"\t\tsetdisplaytext()") $o2.save(tstr) sprint(tstr,"\t}") $o2.save(tstr) sprint(tstr,"\t{object_pop()}") $o2.save(tstr) } endtemplate MRC_LoopParameter begintemplate MRC_OutputVariableType public gettype, gettypestr,loadhandlerclass,createhandler, virtual strdef typestr objref handlerclass, nil public settypeindex,gettypeindex external MRC_debugmode proc init(){ typestr=$s1 virtual=$2 handlerclassloaded=0 typeindex=0 } proc gettypestr(){ $s1=typestr } proc settypestr(){ typestr=$s1 } proc settypeindex(){ typeindex=$1 } func gettypeindex(){ return typeindex } proc loadhandlerclass(){ handlerclass=$o1 if(nil!=handlerclass){ handlerclassloaded=1 } } obfunc createhandler(){ if(1==handlerclassloaded && 2==numarg()){ //print "handlerclass:", handlerclass return handlerclass.createhandler($o1,$o2) }else{ if(1==MRC_debugmode){ if(1!=handlerclassloaded){ printf("Handlerclass not loaded!") } if(2!=numarg()){ printf("In correct number of arguments for createhandler() in object:%s",this) } } return nil } } endtemplate MRC_OutputVariableType begintemplate MRC_OutputVariable public name, displaytext, inuse public settype, gettype, gethandler, getprotocol,setprotocol public setdisplaytext, toggle public get_sessionstr objref nil,this objref type, handler, protocol strdef useicon, name, displaytext, tstr external MRC_debugmode proc init(){ if(0!=numarg()){ use=1 if(MRC_debugmode==1 && numarg()!=3){ printf("Incorrect initialization of MRC_OutputVariable") } name=$s1 // Don't change the order of the setprotocol and settype statements, // settype requires that the protocol is known because protocol is passed // to the newly instantiated handler. setprotocol($o3) settype($o2) setdisplaytext() } } proc settype(){ if(numarg()==1){ type=$o1 createhandler() }else{ if(MRC_debugmode==1 ){ printf("MRC_OutputVariable:settype, Incorrect number of parameters") } } //print "MRC_OutputVariable,type: " , type } proc setprotocol(){ protocol=$o1 } obfunc getprotocol(){ return protocol } proc createhandler(){ if(1!=type.virtual){ objref handler handler=type.createhandler(this,protocol) setdisplaytext() } } obfunc gethandler(){ return handler } obfunc gettype(){ return type } proc toggle() { use = (use+1)%2 setdisplaytext() } func inuse() { return use } proc setdisplaytext(){ //print "MRC_OutputVariable,setdisplaytext: " , type type.gettypestr(tstr) if (use) { useicon="+" }else{ useicon="-" } sprint(displaytext,"%s %s %s",useicon,name, tstr) } proc get_sessionstr(){ // Because there is no way of knowing whether a block is open or closed we adopted the convention that // get_sessionstr only returns closed blocks and we make the calling code responsible for closing and // opening blocks before and after the current blocks. $s1="" //sprint(tstr,"\n{tobj.setprotocol(protocol)}") sprint(tstr,"{tobj1=types_outpar.gettypefromindex(%d)}",type.gettypeindex()) $o2.save(tstr) sprint(tstr,"{tobj=new MRC_OutputVariable(\"%s\",tobj1,protocol)}",name) $o2.save(tstr) sprint(tstr,"\t{object_push(tobj)}") $o2.save(tstr) sprint(tstr,"\t{") $o2.save(tstr) sprint(tstr,"\t\tuse=%d",use) $o2.save(tstr) sprint(tstr,"\t\tsetdisplaytext()") $o2.save(tstr) sprint(tstr,"\t}") $o2.save(tstr) sprint(tstr,"\t{object_pop()}") $o2.save(tstr) if(1!=type.virtual){ sprint(tstr,"{tobj1=tobj.gethandler()}") $o2.save(tstr) sprint(tstr,"\t{object_push(tobj1)}") $o2.save(tstr) handler.get_sessionstr(tstr, $o2) sprint(tstr,"\t{object_pop()}") $o2.save(tstr) } } proc unref(){local refcount refcount=$1 //print "MRC_OutputVariable,unref: " , type if(1==refcount){ //remove references objref handler } } endtemplate MRC_OutputVariable begintemplate MRC_Protocol public output_matlab_mfile, output_neuronbinary, output_axontextfile,get_sessionstr, edit objref vbox strdef tstr proc init(){ output_matlab_mfile=1 // text format for matlab output_neuronbinary=0 // See Konstantin Miller's contribution the NEURON forum // about possibilities to import this into matlab: // http://www.neuron.yale.edu/phpBB2/viewtopic.php?p=289&highlight=&sid=c2249fea8c8a6f51d76b5f56c9150921#289 // Supported precisions:'double','float32','int' output_axontextfile=0 // For love of the ascii format, and to pay experimenters in their own currency. // Requires a proper protocol class dialog_outcome=0 loutput_matlab_mfile=output_matlab_mfile loutput_neuronbinary=output_neuronbinary loutput_axontextfile=output_axontextfile } proc createeditwindow(){ vbox=new VBox() vbox.intercept(1) xpanel("") xcheckbox("Make printtofile generate matlab output",&loutput_matlab_mfile) xcheckbox("Make printtofile generate neuron binary output",&loutput_neuronbinary) //xcheckbox("Use indexing (sections only)",&loutput_axontextfile) xpanel() vbox.intercept(0) doNotify() dialog_outcome=vbox.dialog("Protocol Settings ","Accept","Cancel") } proc edit(){ dialog_outcome=0 loutput_matlab_mfile=output_matlab_mfile loutput_neuronbinary=output_neuronbinary loutput_axontextfile=output_axontextfile createeditwindow() if(1==dialog_outcome){ output_matlab_mfile=loutput_matlab_mfile output_neuronbinary=loutput_neuronbinary output_axontextfile=loutput_axontextfile } } proc savetofile(){ } proc get_sessionstr(){ // Because there is no way of knowing whether a block is open or closed we adopted the convention that // get_sessionstr only returns closed blocks and we make the calling code responsible for closing and // opening blocks before and after the current blocks. $s1="" sprint(tstr,"{tobj=new MRC_Protocol()}") $o2.save(tstr) sprint(tstr,"\t{object_push(tobj)}") $o2.save(tstr) sprint(tstr,"\t{") $o2.save(tstr) sprint(tstr,"\t\toutput_matlab_mfile=%d",output_matlab_mfile) $o2.save(tstr) sprint(tstr,"\t\toutput_neuronbinary=%d",output_neuronbinary) $o2.save(tstr) sprint(tstr,"\t\toutput_axontextfile=%d",output_axontextfile) $o2.save(tstr) sprint(tstr,"\t}") $o2.save(tstr) sprint(tstr,"\t{object_pop()}") $o2.save(tstr) } endtemplate MRC_Protocol //Here you can define classes for handling output, which will be used to for future extension of the number of handler classes obfunc MRC_CreateOutParamHandler(){localobj nil return nil } strdef MRC_ListGenerator_Str objref MRC_ListGenerator_DummyObject, MRC_ListGenerator_NetCon, nil obfunc MRC_GetObjectFromName() {localobj returnobj if(0!=name_declared($s1)){ sprint(MRC_ListGenerator_Str,"MRC_ListGenerator_DummyObject=%s",$s1) execute1(MRC_ListGenerator_Str) returnobj=MRC_ListGenerator_DummyObject } return returnobj } obfunc MRC_OutvecListGenerator() {local listtype,index localobj outveclist,outvec,netcon,netconlist, sources, seclist listtype=$1 isart=$2 //listname=$s3 //sectionname=$s4 //membername=$s5 netconlist=$o6 //shortname=$s7 useindexing=$8 outveclist= new List() //Just a reminder about the correspondence // "List", "llisttype=0" // "Section/Set of sections", "llisttype=2" // "SectionList", "llisttype=3" if(0==listtype ){ sources=MRC_GetObjectFromName($s3) if(0==listtype){ for all_in_list (sources,&index){ outvec =new Vector() if(0==isart){ sprint(MRC_ListGenerator_Str,"%s.object(%d).%s MRC_ListGenerator_NetCon= new NetCon(&%s,nil)" ,$s3,index,$s4,$s5) }else{ sprint(MRC_ListGenerator_Str,"MRC_ListGenerator_NetCon= new NetCon(%s.object(%d),nil)" ,$s3,index) } execute1(MRC_ListGenerator_Str) netcon=MRC_ListGenerator_NetCon netconlist.append(netcon) netcon.record(outvec) outveclist.append(outvec) //sprint(MRC_ListGenerator_Str,"%s_%d" ,$s7,index) sprint(MRC_ListGenerator_Str,"%s{%d}" ,$s7,index+1) outvec.label(MRC_ListGenerator_Str) } } }else if(2==listtype || 3==listtype){ if(2==listtype){ seclist =new SectionList() forsec $s3 { seclist.append() } } if(3==listtype){ seclist = MRC_GetObjectFromName($s3) } index=0 forsec seclist { outvec =new Vector() sprint(MRC_ListGenerator_Str,"MRC_ListGenerator_NetCon= new NetCon(&%s,nil)" ,$s5) execute1(MRC_ListGenerator_Str) netcon=MRC_ListGenerator_NetCon netconlist.append(netcon) netcon.record(outvec) outveclist.append(outvec) if(1==useindexing){ sprint(MRC_ListGenerator_Str,"%s_%d" ,$s7,index) }else{ sprint(MRC_ListGenerator_Str,"%s_%s" ,$s7,secname()) } outvec.label(MRC_ListGenerator_Str) index=index+1 } }else if(4==listtype){ outvec =new Vector() sprint(MRC_ListGenerator_Str,"MRC_ListGenerator_NetCon= new NetCon(%s,nil)" ,$s3) execute1(MRC_ListGenerator_Str) netcon=MRC_ListGenerator_NetCon netconlist.append(netcon) netcon.record(outvec) outveclist.append(outvec) sprint(MRC_ListGenerator_Str,"%s",$s7) outvec.label(MRC_ListGenerator_Str) }else{ if(1==isart){ outvec =new Vector() sprint(MRC_ListGenerator_Str,"MRC_ListGenerator_NetCon= new NetCon(&%s,nil)" ,$s3,index) execute1(MRC_ListGenerator_Str) netcon=MRC_ListGenerator_NetCon netconlist.append(netcon) netcon.record(outvec) outveclist.append(outvec) sprint(MRC_ListGenerator_Str,"%s_%d" ,$s7,index) outvec.label(MRC_ListGenerator_Str) }else{ if(1==MRC_debugmode){ printf("Use a section list, to specify the information needed for building a list.") } } } return outveclist } proc MRC_SeparateSecAndIndex(){local BraIndex, KetIndex, Length localobj StrFies StrFies= new StringFunctions() $s2=$s1 $s3="" BraIndex=StrFies.substr($s1, $s4) if(BraIndex>=0){ KetIndex=StrFies.substr($s1, $s5) $s3=$s1 StrFies.left($s2,BraIndex) StrFies.left($s3,KetIndex) StrFies.right($s3,BraIndex+1) } } begintemplate UndefinedOutParamHandler public editsettings, createhandler,edit,preparerun,printtofile,show,get_sessionstr objref nil objref vbox external MRC_debugmode proc init(){ if(1==MRC_debugmode && numarg()>0){ printf("Cannot initialize undefined class with an MRC_OutputVariable or other object, please set properties again after picking the outpoutvariable type!") } } obfunc createhandler(){ if(1==MRC_debugmode){ printf("Cannot create new instance of the undefined class, its supposed to be a singleton!") } return nil } func editsettings(){ vbox=new VBox() vbox.intercept(1) dialog_outcome=vbox.dialog("Define a type first!","Accept","or Accept anyway!") vbox.intercept(0) return 0 } proc edit(){ //Stub } proc preparerun(){ //Stub } proc printtofile(){ //Stub } proc show(){ //Stub } proc get_sessionstr(){ } endtemplate UndefinedOutParamHandler load_file("MRC_TimeSeriesHandler.hoc") load_file("MRC_SpikeTrainHandler.hoc") load_file("MRC_ScalarHandler.hoc") begintemplate MRC_OutParamHandlerContainer public get_undefined_type public gettypefromindex, object, count // List member functions objref undefined_type, undefined_obj // variables for the one and only instance of the UndefinedOutParam objref defined_type, defined_obj objref types // Procedure to create types, the types are later used to instantiate // handler from th eassociated types, because the session file mechanism // relies on the index in the list "types" new handler classes should be added at // the bottom of the procedure. proc init(){localobj type types =new List() type_index=-1 // Undefined type undefined_type =new MRC_OutputVariableType("--Undefined--",1) undefined_obj=new UndefinedOutParamHandler() undefined_type.loadhandlerclass(undefined_obj) type_index=types.append(undefined_type)-1 undefined_type.settypeindex(type_index) // Time Series defined_type = new MRC_OutputVariableType(" Time Series ",0) defined_obj = new TimeSeriesHandler() defined_type.loadhandlerclass(defined_obj) type_index=types.append(defined_type)-1 defined_type.settypeindex(type_index) // Spiketrain defined_type = new MRC_OutputVariableType(" Spiketrain ",0) defined_obj = new SpikeTrainHandler() defined_type.loadhandlerclass(defined_obj) type_index=types.append(defined_type)-1 defined_type.settypeindex(type_index) // Scalar defined_type = new MRC_OutputVariableType(" Scalar ",0) defined_obj = new ScalarHandler() defined_type.loadhandlerclass(defined_obj) type_index=types.append(defined_type)-1 defined_type.settypeindex(type_index) } obfunc gettypefromindex(){ // for readable code return object($1) } obfunc object(){ // for use with all_in_list iterator return types.object($1) } obfunc get_undefined_type(){ return undefined_type } func count(){ return types.count() } endtemplate MRC_OutParamHandlerContainer //load_file("MRC_Test.hoc") //load_file("../PilotWt/Pilot_WT_NetV2.hoc")