objref gabaAsyn, gabaBsyn, ampasyn, nmdasyn
objref gabaAsyn1, gabaBsyn1, ampasyn1, nmdasyn1
objref gabaAsyn2, gabaBsyn2, ampasyn2, nmdasyn2
objref synstim, stim[3], stim2[3], g[5], h[3], insr1, insr2, flex1, flex2
objref save_window_, ocbox_, mt, fmechs, NULL 
strdef fname, mname
double xstatedum[17]	

load_file("stdgui.hoc")

steps_per_ms= 10
dt= 0.05

create soma 
create cell1
create cell2






proc continuerun() {local rt
// I copied this procedure from stdrun.hoc and got rid of the doNotify()
// command that makes the simulation crash when a panel 
// displays a parameter that doesn't exist because the mechanism has been 
// uninserted. Now the values of the dynamic variables are updated in the 
// panels after the simulation. 
 
        eventcount=0
        eventslow=1
        stoprun = 0
        while(t < $1 && stoprun == 0) {
                step()
                rt = stopsw()
                if (rt > realtime) {
                        realtime = rt
                        fastflushPlot()
                //      doNotify()
                        if (realtime == 2 && eventcount > 50) {
                                eventslow = int(eventcount/50) + 1
                        }
                        eventcount = 0
                }else{
                        eventcount = eventcount + 1
                        if ((eventcount%eventslow) == 0) {
                                doEvents()
                        }
                }
        }
        flushPlot()
}

proc create_inserter1(){
   if (object_id(insr1)) insr1.v1.unmap()
   insr1= new Inserter()
}

proc create_inserter2(){
   if (object_id(insr2)) insr2.v1.unmap()
   insr2= new Inserter()
}

proc create_flexparpanel(){ 
   if (!ismembrane("cadyn")) ion_style("ca_ion",1,2,1,0,0)
   if (!strcmp("cell2",secname())) {
	flex2= new HBox() 
        flex2.intercept(1)
        nrnsecmenu(.5,1)  
        flex2.intercept(0)
        flex2.map("Cell2: Parameters")
   } else {
   	flex1= new HBox()
   	flex1.intercept(1)
   	nrnsecmenu(.5,1)
   	flex1.intercept(0)
   	if (!strcmp("cell1",secname())) { 
		flex1.map("Cell1: Parameters") 
	} else { 
		flex1.map("My Own Cell: Parameters") }
   }
}

proc create_graphs(){
   h[2]= new VBox()
   h[2].intercept(1)
   
   g[4]= new Graph(0)
   g[4].view(0,0,0,0,0,0,300,60)
   g[4].xaxis(3) g[4].yaxis(3)
   graphList[1].append(g[4])
   g[4].save_name("graphList[1].")
   g[4].label( 1, 1, "")
   g[4].addexpr("stim[0].i+stim[1].i", 1, 2)
   g[4].label( .5, .8, "current injection")
   
   for i=0,3 { g[i]= new Graph(0) g[i].view(0,0,0,0,0,0,300,150)}
   graphList[0].append(g[0])
   graphList[1].append(g[1])
   graphList[1].append(g[2])
   graphList[2].append(g[3]) 
   g[0].save_name("graphList[0].")
   g[1].save_name("graphList[1].")
   g[2].save_name("graphList[1].")
   g[3].save_name("graphList[2].")
   h[2].intercept(0)
   h[2].map("Graphs")

   // graph labels will be printed below the following dummy labels
   // remember to put the .addvar and .addexpr commands before the .size
   // command since the .size command will mess up the labeling system
   g[0].label( .5, 1, "")
   g[1].label( .5, 1, "")  
   g[2].label( .5, 1, "")
   g[3].label( .5, 1, "")
}

proc create_graphs2(){ 
   newPlotV()
}

proc create_graphs3(){ 
   newPlot(0,tstop,-100,40)
   graphItem.save_name("graphList[0].")
   graphList[0].append(graphItem) 
   graphItem.addvar("cell1.v(.5)", 1, 0)
   graphItem.addvar("cell2.v(.5)", 2, 0)
}

proc create_maincontrol() {
   xopen("mcontrl1.hoc")
}

proc create_maincontrol2() {
   xopen("mcontrl2.hoc")
} 

proc create_maincontrol3() {
   xopen("mcontrl3.hoc")
}

proc create_parpanel(){
   xopen("parpanl1.hoc")
}

proc create_parpanel2(){
   xopen("parpanl2.hoc")
}

proc create_parpanel3(){
   xopen("parpanl3.hoc")
}

proc current_description(){
	currentnr= $1
	xopen("plotcurr.hoc")
}

proc initmy1stcell(){
	access soma
        //* total membrane area of 29000 uM^2
        L = 290/PI
        diam = 100

	insert leak uninsert leak // this inserts all the ionic concentrations
	insert iCAN ecan= -20 uninsert iCAN
	insert iH eh= -43 uninsert iH
	uninsert cadyn
	ion_style("ca_ion",1,2,1,0,0)

	synstim= new SynStim(0.99)	// point processes need to be 
					// located somewehere

	ampasyn.w= nmdasyn.w= gabaAsyn.w= gabaBsyn.w= 0

	ampasyn1= new AMPA(0.5) 
	gabaAsyn1= new GABA(0.5)
	gabaBsyn1= new GABAB1(0.5)
	nmdasyn1= new NMDA(0.5)

	setpointer ampasyn1.pre, synstim.sAmpa(0.99)
	setpointer nmdasyn1.pre, synstim.sNmda(0.99)
	setpointer gabaAsyn1.pre, synstim.sGabaA(0.99)
	setpointer gabaBsyn1.pre, synstim.sGabaB(0.99)
	
	Prethresh= 0.999		// release only at peak of sinusoid
	ampasyn1.Prethresh= Prethresh
	nmdasyn1.Prethresh= Prethresh
	gabaAsyn1.Prethresh= Prethresh
	gabaBsyn1.Prethresh= Prethresh

	stim[0]= new IClamp(0.5)
	stim[1]= new IClamp(0.5)
	stim[2]= new VClamp(0.5)

	stim[0].dur= 1e10
}

proc initmy1st2cells(){  

	celsius = 35
	tstop = 100
        
	access cell1
	        //* total membrane area of 29000 uM^2
        	L = 290/PI
        	diam = 100

//		insert leak uninsert leak
//		insert iCAN ecan= -20 uninsert iCAN
//		insert iH eh= -43 uninsert iH	
	
//        	cai = 2.4e-4
//        	cao = 2  
//      	nai = 31 
//        	nao = 145
//        	ki = 135
//        	ko = 3.1 
//        	cli = 7  
//        	clo = 120
//        	mgo = 1

 		ampasyn2= new AMPA(0.5)
        	gabaAsyn2= new GABA(0.5)
        	gabaBsyn2= new GABAB1(0.5)
        	nmdasyn2= new NMDA(0.5)  

	        stim[0]= new IClamp(0.5)
        	stim[1]= new IClamp(0.5)
        	stim[2]= new VClamp(0.5)

		stim[0].dur= 1e10

	access cell2
               //* total membrane area of 29000 uM^2
                L = 290/PI
                diam = 100

//	        insert leak uninsert leak
//		insert iCAN ecan= -20 uninsert iCAN
//		insert iH eh= -43 uninsert iH

//              cai = 2.4e-4
//              cao = 2 
//              nai = 31 
//              nao = 145
//              ki = 135
//              ko = 3.1
//              cli = 7  
//              clo = 120
//              mgo = 1

		ampasyn1= new AMPA(0.5)
        	gabaAsyn1= new GABA(0.5)
        	gabaBsyn1= new GABAB1(0.5)
        	nmdasyn1= new NMDA(0.5)

	        stim2[0]= new IClamp(0.5)
        	stim2[1]= new IClamp(0.5)
        	stim2[2]= new VClamp(0.5)
	
		stim2[0].dur= 1e10

	setpointer ampasyn2.pre, cell2.v(0.5)
	setpointer nmdasyn2.pre, cell2.v(0.5)  
	setpointer gabaAsyn2.pre, cell2.v(0.5)
	setpointer gabaBsyn2.pre, cell2.v(0.5)

	setpointer ampasyn1.pre, cell1.v(0.5)
	setpointer nmdasyn1.pre, cell1.v(0.5)
	setpointer gabaAsyn1.pre, cell1.v(0.5)
	setpointer gabaBsyn1.pre, cell1.v(0.5)
}

proc initsoma(){
	access soma

        //* total membrane area of 29000 uM^2
        L = 290/PI
        diam = 100

	celsius = 35
	tstop = 100
	
	insert leak
	insert HH
	insert iA  
	insert iAHP
	insert iC
	insert iL
	insert iM
	insert iT
	insert cadyn

	cai = 2.4e-4 
        cao = 2 
	nai = 31
	nao = 145
	ki = 135
	ko = 3.1
	cli = 7
	clo = 120
	mgo = 1
		
	ampasyn= new AmpaSynapse(0.5) 
	gabaAsyn= new GABAaSynapse(0.5)
	gabaBsyn= new GABAbSynapse(0.5)
	nmdasyn= new NmdaSynapse(0.5)

	stim[0]= new IClamp(0.5)
	stim[1]= new IClamp(0.5)
	stim[2]= new VClamp(0.5)
}

proc main(){
	initsoma()
	create_maincontrol()
}

proc make_coords_visible(){ local ylen
   make_ycoords_visible()

   scale_axes_cclamp_plot()
   // the time values may not be fully visible if the y-axis starts at y=0
   for i=0,3 {
      ylen= g[i].size(4)-g[i].size(3)
      g[i].size(-.05*tstop,tstop,g[i].size(3)-.05*ylen,g[i].size(4)+.05*ylen)
   }

   // create some new dummy labels as the .size commands in the parameter files
   // messes up the labeling system, user created graphs will have labels printed
   // below the following dummies 
   g[0].label( .5, 1, "")
   g[1].label( .5, 1, "")
   g[2].label( .5, 1, "")
   g[3].label( .5, 1, "")
}

proc make_ycoords_visible(){
   // if the user changes tstop the y-coordinates may not be visible anymore
   if (object_id(g[4])) {
      for i=0,4 g[i].size(-.05*tstop, tstop, g[i].size(3), g[i].size(4)) 
   }
}

proc my_first_cell() {
	if (object_id(h[2])) h[2].unmap
	for i=0,3 graphList[i].remove_all
        graphItem = NULL

	initmy1stcell()
	create_maincontrol2()
	create_parpanel2()
	create_graphs2()
}

proc my_first_2cells() {
        if (object_id(h[2])) h[2].unmap
        for i=0,3 graphList[i].remove_all
        graphItem = NULL

	create soma

        initmy1st2cells()
        create_maincontrol3()
        create_parpanel3()
	create_graphs3()   
}

proc myrun(){
   update_synaptic_parameters()
   run()
}

proc new_experiment() {
	initsoma() 	  // this is redundant but prevents uninserted channels
	reset_soma_pars()

	for i=0,3 graphList[i].remove_all
	graphItem = NULL
	create_graphs()

	// set the states of the experiment xcheckboxes 
	for i=0,16 xstatedum[i]= 0
	xstatedum[$1-1]= 1

	if ($1==1) xopen("e1.par")
	if ($1==2) xopen("e3.par")
	if ($1==3) xopen("e5.par")
	if ($1==4) xopen("e7.par")
	if ($1==5) xopen("e10.par")
	if ($1==6) xopen("e11a.par")
	if ($1==7) xopen("e11b.par")
	if ($1==8) xopen("e12.par")
	if ($1==9) xopen("e13.par")
	if ($1==10) xopen("e14.par")
	if ($1==11) xopen("e15a.par")
        if ($1==12) xopen("e15b.par")
	if ($1==13) xopen("e16a.par")
        if ($1==14) xopen("e16b.par")
	if ($1==15) xopen("e16c.par")
	if ($1==16) xopen("e17a.par")
        if ($1==17) xopen("e17b.par")

	update_synaptic_parameters()
	create_parpanel()
	make_coords_visible()	
}

proc plot_expression(){ local x,x1,x2,xlen,oldv
	if ($2==1) { x1=-100 x2=100 } else { x1=0 x2=1 }
	xlen= x2-x1
	$o1.size(x1-0.05*xlen,x2+0.05*xlen,$o1.size(3),$o1.size(4))
	if ($2==2) oldv= cai
	$o1.begin()              
	for(x=x1; x<=x2; x=x+0.1) {
	   if ($2==1) { 
	      finitialize(x) $o1.plot(x)
	   } else {
	      cai=x finitialize(v_init) $o1.plot(x)
	   }
	}      
	$o1.flush()
	if ($2==2) cai= oldv
}

proc reset_soma_pars(){
   pk_leak= pna_leak= pcabar_iL= pcabar_iT= 0
   gkbar_HH= gnabar_HH= gkbar_iA= gkbar_iAHP= gkbar_iC= gkbar_iM= 0
   cao0_ca_ion= cli= clo= ki= ko= mgo= nai= nao= 0
   gmax_EPSP= gmax_IPSP= onset_EPSP= onset_IPSP= 0
   taur_cadyn= 1.0 cainf_cadyn= 5e-5 kt_cadyn= 0.0 kd_cadyn= 5e-5
   celsius= 35
   ampasyn.w= nmdasyn.w= gabaAsyn.w= gabaBsyn.w= 0
   for i=0,1 { stim[i].amp= stim[i].del= stim[i].dur= 0 }
   stim[0].dur= 9999  // base current
   for i=0,2 { stim[2].dur[i]= stim[2].amp[i]= 0 }
}

proc retrieve_session(){ strdef f
        fmechs = new File()
        fmechs.chooser("","Retrieve parameters and graphs","*.ses","Retrieve")
        if (fmechs.chooser()) {
           fmechs.getname(mname)
           xopen(mname)
	   if (object_id(ocbox_)) {
	      execute("h[2]= ocbox_")
	      execute("ocbox_= NULL")
	   }
	   g[4]=graphList[1].object(0)
	   g[0]=graphList[0].object(0)
	   g[1]=graphList[1].object(1)
	   g[2]=graphList[1].object(2)
	   g[3]=graphList[2].object(0)

	   create_parpanel()
	   update_synaptic_parameters()
	   make_coords_visible()

	   // set the states of the experiment xcheckboxes
           for i=0,16 xstatedum[i]= 0
        }
}

proc retrieve_session2(){ 
	create soma
	initmy1stcell()
   	if (object_id(h[0])) h[0].unmap
        for i=0,3 graphList[i].remove_all
        graphItem = NULL

	fmechs = new File()
        fmechs.chooser("","Retrieve cell definition","*.def","Retrieve")
        if (fmechs.chooser()) {
           fmechs.getname(mname)
           xopen(mname)
	}
        fmechs.chooser("","Retrieve parameters and graphs","*.ses","Retrieve")
	if (fmechs.chooser()) { 
           fmechs.getname(mname)
	   xopen(mname)
        }
   	execute("ocbox_= NULL")
        create_parpanel2()
	create_flexparpanel()   
	create_inserter1()
}

proc retrieve_session3(){ 
	create cell1, cell2
	initmy1st2cells()
        if (object_id(h[0])) h[0].unmap
        for i=0,3 graphList[i].remove_all
        graphItem = NULL

        fmechs = new File()
        fmechs.chooser("","Retrieve cell definition","*.def","Retrieve")
        if (fmechs.chooser()) {
           fmechs.getname(mname)
           xopen(mname)
        }
        fmechs.chooser("","Retrieve parameters and graphs","*.ses","Retrieve")
        if (fmechs.chooser()) {
           fmechs.getname(mname)
           xopen(mname)
        }
	execute("ocbox_= NULL")
	create_parpanel3()
	cell1 { create_flexparpanel() create_inserter1() }
	cell2 { create_flexparpanel() create_inserter2() }
}

proc return_from_1cell(){
	if (object_id(h[0])) h[0].unmap
	if (object_id(insr1)) insr1.v1.unmap
	if (object_id(flex1)) flex1.unmap
	for i=0,3 graphList[i].remove_all
	graphItem = NULL
	if (object_id(save_window_)) save_window_ = NULL

	create soma

	main()
}

proc return_from_2cells(){
        if (object_id(h[0])) h[0].unmap
        if (object_id(h[2])) h[2].unmap
	if (object_id(insr1)) insr1.v1.unmap()
	if (object_id(insr2)) insr2.v1.unmap()
	if (object_id(flex1)) flex1.unmap
	if (object_id(flex2)) flex2.unmap

	for i=0,3 graphList[i].remove_all
	graphItem = NULL
	if (object_id(save_window_)) save_window_ = NULL

	create cell1, cell2 

        main()   
}

proc save_session1(){
	xpanel("How to save a session")
	xlabel("To save your parameters and graphs go to the Print & File Window manager.") 
	xlabel("First, select the icon representing the parameter panel in the left virtual screen") 
	xlabel("by clicking on it with the right mouse button. Then, select the icon representing")
	xlabel("the graph panel. Note the specific order, it is crucial for retrieval! To unselect") 
	xlabel("a selected icon, go to the right virtual screen and press the right mouse button")
	xlabel("on the icon. Press the Session button, Save selected, and enter a filename.")
	xlabel("To restore this file, use the Retrieve Session option on the Demo Main Control.")
	xpanel()
}

proc save_session2(){ strdef ss
	// save which mechanisms are inserted and some global parameters
 	mt = new MechanismType(0)
	fmechs = new File()
	fmechs.chooser("","Save cell definition(s)","*.def","Save")
        if (fmechs.chooser()) {
           fmechs.getname(mname)
	   fmechs.wopen(mname)
	   if (issection("soma")) {ss= "soma"} else {ss = "cell"}
	   forsec ss {
	      fmechs.printf("access %s\n", secname())
	      fmechs.printf("L= %f\n", L)
	      for i=0, mt.count()-1 {
	         mt.select(i)
	         mt.selected(mname)
	         if (ismembrane(mname)) {
//	            if (strcmp(mname,"na_ion") && strcmp(mname,"k_ion")) {
//		       if (strcmp(mname,"ca_ion") && strcmp(mname,"cl_ion")) {
//		          if (strcmp(mname,"can_ion") && strcmp(mname,"mg_ion")) {
//		             if (strcmp(mname,"Ca_ion") && strcmp(mname,"h_ion")) {	
		                fmechs.printf("insert %s\n", mname)
//		             }
//		          }
//		       }
//	            }
	         }
	      }
	   }
	   fmechs.printf("\ncao0_ca_ion= %f\n", cao0_ca_ion)
	   fmechs.printf("celsius= %f\n", celsius)
	   fmechs.printf("tstop= %f\n", tstop)
	   fmechs.close()
	} else { break }

	xpanel("How to save a session")
	xlabel("To save your parameters and graphs go to the Print & File Window manager.") 
	xlabel("Select the icons representing the parameter and graph panels in the left virtual")
	xlabel("screen by clicking on it with the right mouse button. To unselect a selected") 
	xlabel("icon, go to the right virtual screen and press the right mouse button on the")
	xlabel("icon. Press the Session button, Save selected, and enter a filename. To restore")
	xlabel("this file use the Retrieve Session option on the appropriate Main Control.")
	xpanel()
}

proc scale_axes_cclamp_plot(){ local dum1,dum2
   // re-optimize y-axis scale of current injection plot due to a change in 
   // amplitude of the injected current by the user    
   if (stim[0].amp<0) dum1= stim[0].amp else dum1= 0
   if (dum1>stim[0].amp+stim[1].amp) dum1= stim[0].amp+stim[1].amp
   if (stim[0].amp>0) dum2= stim[0].amp else dum2=0
   if (dum2<stim[0].amp+stim[1].amp) dum2= stim[0].amp+stim[1].amp
   if (dum1==dum2) dum2= dum2+1
   g[4].size(g[4].size(1), g[4].size(2), dum1, dum2+.5*(dum2-dum1))
}

proc series_voltagestep(){ local from, to, s
        from= $1
        to= $2
        s= stim[2].amp[1]      // save copy of old value and restore later
        for (i=from; i<=to; i=i+10){
	  if (stoprunseries) break	
          stim[2].amp[1]= i
          finitialize(v_init)
          run()
        }
	stoprunseries= 0
        stim[2].amp[1]= s
}

proc update_synaptic_parameters(){
   ampasyn.gmaxEPSP= nmdasyn.gmaxEPSP= gmax_EPSP
   gabaAsyn.gmaxIPSP= gabaBsyn.gmaxIPSP= gmax_IPSP
   ampasyn.onset= nmdasyn.onset= onset_EPSP
   gabaAsyn.onset= gabaBsyn.onset= onset_IPSP
}

xopen("about.hoc")
main()