begintemplate ShowConnect
public smode_, hinton_movie, sim
external reload_onecell, reload_wholenet, pc, weight_movie
external allsyn, somesyn, cells, flush_list, cvode, len, addplot, tstop
external clear, create_stim, create_cells, connect_cells, gidvec, classname
objref g, syns, msel, gsel, mgrsel, msynsel, gsynsel, synsel1, deck
objref b, v_rvp_, keepsyn, keepnc, hinton_shape, tplots
objref syn_movie_fih, syn_movie_list, syn_movie_nclist, this
objref mitral_x, granule_x
strdef sel_str_
create keepsyn_sec
proc init() {
	tplots = new List()
	hinton_movie = 0
	keepsyn_sec { delete_section() }
	smode_ = -1
	wholenet_ = 1
	sel_str_ = "no selection"
	sel_gid_ = -1
	cells = $o1
	ls = cells.object(0).secden[1].L
	nmitral = $2
	ngranule = $3
	syns = $o4
	msel = new Vector(nmitral)
	gsel = new Vector(ngranule)
	msynsel = new Vector(nmitral) // all synapses assocated with mitral
	gsynsel = new Vector(ngranule)
	mgrsel = new Vector(syns.count)
	synsel1 = new Vector(syns.count)
	save_for_draw()
	build()
	draw()
}
proc save_for_draw() {
	//mitral and granule positions
	mitral_x = new Vector()
	granule_x = new Vector()
	for i=0, nmitral-1 {
		pc.gid2cell(i).soma mitral_x.append(x3d(0))
	}
	for i=0, ngranule-1 {
		pc.gid2cell(nmitral + i).soma granule_x.append(x3d(0))
	}		
}
proc build() {local mx1, mx2, gx1, gx2
	b = new HBox()
	b.intercept(1)
	b.full_request(1)
	b.adjuster(520)
	g = new Graph(0)
	g.view(0,0,1,1,0,0,520,130)
	cells.object(0).soma mx1 = x3d(0)
	cells.object(nmitral-1).soma mx2 = x3d(0)
	cells.object(nmitral).soma gx1 = x3d(0)
	cells.object(nmitral+ngranule-1).soma gx2 = x3d(0)
	if ( gx1 < mx1) mx1 = gx1
	if ( gx2 > mx2) mx2 = gx2
	g.size(mx1, mx2, -1, nmitral)
//	g.size(-ls + mx1, ls + mx2, -1, nmitral)
	
	g.xaxis(3)
	deck = new Deck()
	deck.intercept(1)
	xpanel("")
	g.menu_tool("Select cells", "select", "smode(1)")
	g.menu_tool("Select all synapses of cells", "select", "smode(2)")
	g.menu_tool("Select a few synapses", "select", "smode(3)")
	xcheckbox("Hinton synapse movie", &hinton_movie)
//	xvarlabel(sel_str_)
	xbutton("Simulate", "sim()")
	xpanel()
	xpanel("")
	xbutton("Reload entire net", "whole_net()")
	xpanel()
	deck.intercept(0)
	deck.flip_to(0)
	deck.map()
	b.intercept(0)
	b.map("Select Subset", 400, 30, 700, 180)
	g.exec_menu("Select cells")
}
proc draw() {local i, j, k, x, mx, mi, gi, b, def_color   localobj mgr, sr
	def_color = 1
	if (wholenet_ == 0) { def_color = 9 }
	g.erase()
	for i=0, nmitral-1 {
		x = mitral_x.x[i]
		g.beginline(9, 1)
		g.line(-ls + x, i)
		g.line(ls + x, i)	
		g.flush()
		if (msel.x[i] == 1) {
			g.mark(x, i, "T", 10, 2, 1)
		}else{
			g.mark(x, i, "t", 10, def_color, 1)
		}
	}
	for i=0, ngranule-1 {
		x = granule_x.x[i]
		if (gsel.x[i] == 1) {
			g.mark(x, -1, "O", 8, 3, 1)
		}else{
			g.mark(x, -1, "o", 8, def_color, 1)
		}
		g.beginline(9, 1)
		g.line(x, nmitral-.5)
		g.line(x, -1)
		g.flush()
	}
	for k=0, syns.count-1 {
		mgr = syns.object(k)
		mi = mgr.mitral_gid
		gi = mgr.granule_gid - nmitral
		x = granule_x.x[gi]
		j = mi
		b = 0
		if (msynsel.x[mi] || gsynsel.x[gi]) {
			b = 1
			g.mark(x, j, "O", 6, 4, 1)
		}else{
			if (msel.x[mi]) {
				b = 1
				if (gsel.x[gi]) {
					g.mark(x, j, "O", 5, 2, 1)
					g.mark(x, j, "o", 6, 3, 2)
				}else{
					g.mark(x, j, "O", 6, 2, 1)
				}
			}else if (gsel.x[gi]) {
				b = 1
				g.mark(x, j, "O", 6, 3, 1)
			}
		}
		if (b == 0) {
			if (wholenet_ == 1) {
				g.mark(x, j, "o", 4, 1, 1)
			}else if (hinton_movie) {
				g.mark(x, j, "O", 3, 1, 1)
			}
		}
		if (synsel1.x[k]) {
			g.mark(x, j, "O", 6, 6, 1)
		}
	}
}
proc smode() {
	if (smode_ != $1) {
		whole_net()
	}
	smode_ = $1
}
proc select() {local m, g, min, x, i, j  localobj mgr
	if (wholenet_ != 1) { return }
	if ($1 == 2) { //press
		//print $1, $2, $3, $4
		if ($3 < -.5) {
			m = -1
		} else {
			m = int($3+.5)
			if (!pc.gid_exists(m)) { m = -1 }
		}
		min = 1e9
		g = -1
		for i=0, ngranule-1 {
			if (!pc.gid_exists(i+nmitral)){continue}
			pc.gid2cell(nmitral+i).soma x = x3d(0)
			if (abs(x - $2) < min) {
				min = abs(x - $2)
				g = i
			}
		}
		//print smode_, m, g
	    if (smode_ == 1) { // selecting a cell
		if (m >= 0) {
			msel.x[m] = (msel.x[m] == 0)
			sel_gid_ = m
			sprint(sel_str_, "mitral gid %d", sel_gid_)
		}else if (g >= 0) {
			gsel.x[g] = (gsel.x[g] == 0)
			sel_gid_ = g + nmitral
			sprint(sel_str_, "granule gid %d", sel_gid_)
		}else{
			sel_gid_ = -1
			sel_str_ = "no selection" 
		}
	    }else if (smode_ == 2) { // selecting all syn for a cell
		if (m >= 0) {
			msynsel.x[m] = (msynsel.x[m] == 0)
			sel_gid_ = m
			sprint(sel_str_, "mitral gid %d", sel_gid_)
		}else if (g >= 0) {
			gsynsel.x[g] = (gsynsel.x[g] == 0)
			sel_gid_ = g + nmitral
			sprint(sel_str_, "granule gid %d", sel_gid_)
		}else{
			sel_gid_ = -1
			sel_str_ = "no selection" 
		}
	    }else{ // select individual synapses
		if (m > -1 && g > -1) {
			g += nmitral
			for i=0, syns.count-1 {
				mgr = syns.o(i)
				if (mgr.mitral_gid == m) if( mgr.granule_gid == g) {
					synsel1.x[i] = synsel1.x[i]==0
				}
			}
		}
	    }
		draw()
	}
}
proc sim() {local i, mk
	if (wholenet_ != 1) { return }
//	if (smode_ != 1) { return }
	deck.flip_to(1)
	wholenet_ = 0
	prune()
	draw()
	for i=0, syns.count-1 if (synsel1.x[i]) {
		syn_graph(i)
	}
	for i=0, msel.size-1 if (msel.x[i]) {
		v_movie(i)
		t_movie(i)
	}
	for i=0, gsel.size-1 if (gsel.x[i]) {
		t_movie(i + nmitral)
	}
	mk = 0
	for i=0, msynsel.size-1 if (msynsel.x[i]) {
		mk = 1
		if (object_id(syn_movie_list) == 0) {
			syn_movie_list = new List()
			syn_movie_nclist = new List()
		}
		syn_movie(i)
	}
	if (hinton_movie) {
		mkhinton()
		mk = 1
	}
	if (mk) {
syn_movie_fih = new FInitializeHandler("cvode.event(0, \"show_weight()\")", this)
	}
	show_weight()
}

proc whole_net() {local i
	pc.gid_clear()
	for i=0, tplots.count-1 {
		tplots.o(i).unmap()
	}
	tplots.remove_all()
	objref keepsyn, keepnc, syn_movie_nclist, syn_movie_fih, syn_movie_list
	objref hinton_shape
	create keepsyn_sec
	keepsyn_sec { delete_section() }
	sel_gid_ = -1
	sel_str_ = "no selection"
	reload_wholenet()
	wholenet_ = 1
	deck.flip_to(0)
	draw()
}

proc v_movie() {localobj g, s
	s = new String()
	g = new Graph(0)	
	g.view(-500, -80, 1000, 120, 400, 500+$1*20, 700, 200)
	v_rvp_ = new RangeVarPlot("v")
	pc.gid2cell($1).secden[1] v_rvp_.begin(1)	
	pc.gid2cell($1).secden[0] v_rvp_.end(1)
	v_rvp_.origin(12.5)
	g.addobject(v_rvp_, 2, 1, 0.8, 0.9)
	sprint(s.s, "mitral gid %d", $1)
	g.label(.3,.9,s.s,2)
	flush_list.append(g)
	tplots.append(g)
}

proc t_movie() {localobj g, s
	s = new String()
	sprint(s.s, "gid %d: %s.soma.v(.5)", $1, pc.gid2cell($1))
	g = new Graph()
	addplot(g, 0)
	g.size(0, tstop, -80, 40)
	tplots.append(g)
	g.label(.3, 1, "", 2)
	pc.gid2cell($1).soma g.addvar(s.s, "v(0.5)", 1, 1) 
}

proc syn_graph() {localobj g, s, mgr
	mgr = syns.o($1)
	s = new String()
	sprint(s.s, "syn (%d, %d)", mgr.mitral_gid, mgr.granule_gid)
	g = new Graph()
	addplot(g, 0)
	g.size(0, tstop, 0, 1)
	tplots.append(g)
	g.label(.3, .9, s.s, 2)
	sprint(s.s, "%s.weight[2]", mgr.gd2fi)
	g.addvar("fi", s.s, 3, 1)
	sprint(s.s, "%s.weight[2]", mgr.md2ampanmda)
	g.addvar("an", s.s, 2, 1)
}

proc syn_movie() {local i localobj g, s, nc, nclist1, nclist2, syn
	s = new String()
	g = new Graph(0)
	g.view(0, 0, len, 1, 400, 250+$1*20, 700, 200)
	
	sprint(s.s, "mitral gid %d", $1)
	g.label(.3,.9,s.s,2)
	syn_movie_list.append(g)
	nclist1 = new List()
	nclist2 = new List()
	for i = 0, syns.count-1 {
		syn = syns.o(i)
		if (syn.mitral_gid == $1) {
			nclist1.append(syn.gd2fi)
			nclist2.append(syn.md2ampanmda)
		}
	}
	syn_movie_nclist.append(nclist1)
	syn_movie_nclist.append(nclist2)
}

proc show_weight() {local i, j, k, x, w  localobj g, nc, syn, nclist
	if (object_id(syn_movie_list)) for i=0, syn_movie_list.count-1 {
		g = syn_movie_list.o(i)
		g.erase()
		for j=0,1 {
			nclist = syn_movie_nclist.o(2*i + j)
			for k = 0, nclist.count - 1 {
				nc = nclist.o(k)
				syn = nc.syn
				x = syn.x
				w = nc.weight[2]
				if (j == 1) {
					g.mark(x, w, "S", 8, 2, 1)
				}else{
					g.mark(x, w, "s", 10, 3, 1)
				}
			}
		}
	}			
	if (object_id(hinton_shape)) {
		hinton_shape.flush()
	}
	cvode.event(t + 100, "show_weight()")
}

proc prune() {local i, mi, gi  localobj pc, keepa, keepf, mgr, nil, cell
	pc = new ParallelContext()
	pc.gid_clear()
	// 0 - destroy, 1 - keep where it is, 2 - move to safe place
	keepa = new Vector(syns.count)
	keepf = new Vector(syns.count)
	if (hinton_movie) { keepa.fill(2)  keepf.fill(2) }
	for i=0, syns.count-1 {
		mgr = syns.o(i)
		mi = mgr.mitral_gid
		gi = mgr.granule_gid - nmitral
		if (msynsel.x[mi]) {keepa.x[i] = 2  keepf.x[i] = 2 }
		if (gsynsel.x[gi]) {keepa.x[i] = 2  keepf.x[i] = 2 }
		if (synsel1.x[i]) {keepa.x[i] = 2  keepf.x[i] = 2 }
	}
	for i=0, syns.count-1 {
		mgr = syns.o(i)
		mi = mgr.mitral_gid
		gi = mgr.granule_gid - nmitral
		if (msel.x[mi]) {keepf.x[i] = 1}
		if (gsel.x[gi]) {keepa.x[i] = 1}
	}
	// move/destroy syns
	for i=0, syns.count-1 {
		mgr = syns.o(i)
		mgr.gd = nil
		mgr.md = nil
		if (keepf.x[i] == 2) {
			if (!section_exists("keepsyn_sec", this)) {
				create keepsyn_sec
			}
			keepsyn_sec mgr.fi.loc(.5)
			mgr.mitral = nil
		}
		if (keepa.x[i] == 2) {
			if (!section_exists("keepsyn_sec", this)) {
				create keepsyn_sec
			}
			keepsyn_sec mgr.ampanmda.loc(.5)
			mgr.granule = nil
		}
		if (keepf.x[i] == 0) {
			mgr.gd2fi = nil
			mgr.fi = nil
			mgr.mitral = nil
			mgr.granule = nil
		}
		if (keepa.x[i] == 0) {
			mgr.md2ampanmda = nil
			mgr.ampanmda = nil
			mgr.mitral = nil
			mgr.granule = nil
		}
	}
	// destroy cells
	for (i = cells.count-1; i >= 0; i -= 1) {
		cell = cells.o(i)
		if (i < nmitral) if(msel.x[i]) {
			pc.set_gid2node(i, pc.id)
			cell.soma pc.cell(i, new NetCon(&v(.5), nil))
			continue
		}
		if (i > nmitral) if (gsel.x[i - nmitral]) {
			pc.set_gid2node(i, pc.id)
			cell.soma pc.cell(i, new NetCon(&v(.5), nil))
			continue
		}
		cells.remove(i)
		cell = nil
	}
	// recreate connection using the original NetCon
	for i=0, syns.count-1 {
		mgr = syns.o(i)
		if (mgr.fi != nil) {
			pc.gid_connect(mgr.gd_gid, mgr.fi, mgr.gd2fi)
		}
		if (mgr.ampanmda != nil) {
			pc.gid_connect(mgr.md_gid, mgr.ampanmda, mgr.md2ampanmda)
		}
	}
}

proc mkhinton() {local i, mx1, mx2, xmin, xmax, dx, ymin, ymax, yscl \
  localobj syn, sl, g
	xmin = 0  xmax = len
	dx = len/ngranule
//print "dx=", dx
	ymin = 0  ymax = nmitral
	yscl = (xmax - xmin)/(ymax - ymin) * 250/700 *.9
	if (dx > yscl/2) { dx = yscl/2 * .9 }
//	hinton_build()
//proc hinton_build() {local mx1, mx2, sl
	sl = new SectionList()
	g = new PlotShape(sl,0)
	hinton_shape = g
	g.view(xmin, ymin, xmax-xmin, (ymax-ymin)*yscl, 400, 250, 700, 250)
	g.colormap(11)
	i = -1
g.colormap(i+=1, 111,  0,    111)
g.colormap(i+=1, 143,  0,    127)
g.colormap(i+=1, 175,  0,    95)
g.colormap(i+=1, 207,  0,    63)
g.colormap(i+=1, 223,  47,   47)
g.colormap(i+=1, 255,  79,   15)
g.colormap(i+=1, 255,  111,  0)
g.colormap(i+=1, 255,  143,  0)
g.colormap(i+=1, 255,  175,  0)
//g.colormap(i+=1, 255,  207,  0) 
g.colormap(i+=1, 255,  239,  0)
//g.colormap(i+=1, 255,  255,  0)
g.colormap(i+=1, 255,  255,  200)

	g.scale(-.1, 1.1)
	g.exec_menu("Shape Plot")
	sl = new SectionList()
	g = new PlotShape(sl,0)
	g.view(xmin, ymin, xmax-xmin, (ymax-ymin)*yscl, 400, 250, 700, 250)
	g.scale(-.1, 1.1)
	g.exec_menu("Shape Plot")
	hinton_draw(dx)
}
proc hinton_draw() {local i, x, m, b, dx  localobj ncl, nc, syn, sr, s
	dx = $1
	s = new String()
	ncl = new List("NetCon")
	for i=0, ncl.count-1 {
		nc = ncl.object(i)
		syn = nc.syn
		classname(syn, s.s)
		if (strcmp(s.s, "FastInhib") == 0) {
			b = 1
		}else if (strcmp(s.s, "AmpaNmda") == 0) {
			b = 0
		}else{
			continue
		}
		x = syn.x
		m = syn.mgid		
		nc.weight[2] = 0
		hinton_shape.hinton(&nc.weight[2], x, m*3*dx+(dx)*b, dx-2)
	}
}

endtemplate ShowConnect

objref sc_
proc showconnect() {
	sc_ = new ShowConnect(cells, nmitral, ngranule, mgrs_list)
}
showconnect()