begintemplate LogAvsX
public measure, inject, ratio, input, transfer, move_callback, sl, extended, imp
public flush, begin, view_count

objectvar imp, sec, shape, b1, this, move_callback
objref seclist, g, rvp[1], sl

double orig[1]

strdef s0, s1, s2, stemp, sdist, sname, fstyle, tstr

proc init() {
	extended = 0
	direct_ = 0
	style_ = 0
	fstyle = "log(Attenuation)"
	flush_ = 0
	scale_ = 0
	sel_act_ = 0
	sec = new SectionRef()
	x = .5
	outside_sections()
	nsec = 0
	forsec sl { nsec += 1 }
	objref rvp[nsec]
	double orig[nsec]
	freq = 0
	variable_domain(&freq, 0, 1e9) units(&freq, "Hz")
	imp = new Impedance()
	build()
	measure(.5)
}

proc outside_sections() {   
	sl = new SectionList()
	sl.wholetree()
}

proc measure() {
	sec = new SectionRef()
	x = $1
	setdir(direct_)
}

proc setdir() {
    sec.sec {
	direct_ = $1
	if (style_ == 1) { // input
		sprint(s0, "unused (red) %s(%g)", secname(), x)
	}else if (direct_ == 0) {
		sprint(s0, "Measure (red) %s(%g)", secname(), x)
	}else {
		sprint(s0, "Inject (red) %s(%g)", secname(), x)
	}
    }
	draw()
}

proc compute() {  // calcs impedances, argument is freq (Hz)
	sec.sec imp.loc(x)
	imp.compute($1, extended)
}

double sz[4]
proc draw() { local i
	compute(freq)  // freq is set by a field editor
	g.flush()
	if (scale_) {
		g.size(&sz[0])
		g.size(sz[0], sz[1], sz[2], sz[3])
	}
}

proc build() {local i
	b1 = new VBox()
	b1.ref(this)
	b1.save("")
	b1.intercept(1)

	xpanel("", 1)
	xbutton("Redraw", "draw()")
	xmenu("Shape Select Action")
		xradiobutton("Move electrode", "sel_act_ = 0 gcolor()", 1)
		xradiobutton("Show Position", "sel_act_ = 1")
	xmenu()
        xmenu("Plot")
                xradiobutton("log(Attenuation)", "style(0)", 1)
                xradiobutton("Zin (Mohm)", "style(1)")
                xradiobutton("Ztransfer amp (Mohm)", "style(2)")
                xradiobutton("V(measure)/V(inject)", "style(3)")
                xradiobutton("Ztransfer phase (rad)", "style(4)")
        xmenu()   
        xmenu("Extras")
                xstatebutton("Movie mode", &flush_, "add_flush()")
                xstatebutton("Auto Scale", &scale_, "draw()")
	xmenu()
        xpanel()
	xpanel("")
	xcheckbox("include dstate/dt contribution", &extended, "draw()")
	xpvalue("frequency", &freq, 1, "draw()")
	xradiobutton("Vin", "setdir(0)", 1)
	xradiobutton("Vout", "setdir(1)")
	s0 = "     Please Wait       "
	xvarlabel(s0)
	xpanel()

	shape = new Shape()
	g = new Graph()  // appends graph to box
	g.menu_tool("Show position", "show_position")

	color = 2
	shapemark(1)
	shapemark(0, sec, x)

	shape.action("move()")

	b1.intercept(0)
	sprint(stemp, "%s", this)
	b1.map(stemp)

	compute(freq)
	sec.root distance()
	i=-1 forsec sl {i+=1 orig[i] = distance(0)}

	i=-1 forsec sl {i+=1
		rvp[i] = new RangeVarPlot("fun($1)")
		rvp[i].begin(0)
		rvp[i].end(1)
		rvp[i].origin(orig[i])
	}
	add_rvp()
}

proc add_rvp() {local i
	g.erase_all()
	g.label(-100,-100, "")
	for i=0, nsec-1 {
		g.addobject(rvp[i])
	}
	g.label(.5, .9, fstyle)
}

func vmvi() {local xx, y, z
	if (direct_ == 0) {
		y = imp.ratio($1)
	}else{
		sec.sec xx = imp.input(x)
		y = imp.transfer($1)/xx
	}
	if (y*1e20 <= 0) {
		return 1e-30
	}
	return y
}

func fun() {
	if (style_ == 0) {
		return -log(vmvi($1))
	}else if (style_ == 1) {
		return imp.input($1)
	}else if (style_ == 2) {
		return imp.transfer($1)
	}else if (style_ == 4) {
		return imp.transfer_phase($1)
	}else{
		return vmvi($1)
	}
}

proc style() {
	style_ = $1
	if (style_ == 0) {
		fstyle = "log(Attenuation)"
	}else if (style_ == 1) {
		fstyle = "Zin"
	}else if (style_ == 2){
		fstyle = "Ztransfer"
	}else if (style_ == 3) {
		fstyle = "V(measure)/V(inject)"
	}else if (style_ == 4) {
		fstyle = "Ztransfer phase"
	}
	setdir(direct_)
	add_rvp()
	draw()
}

imin=0
proc gcolor() {local i
	i=-1 forsec sl { i+=1
		rvp[i].color(1)
	}
}

proc move() {local i, xx, ss
	xx = hoc_ac_
	rvp[imin].color(1)
	if (sel_act_ == 0) {
		measure(xx)
		shapemark(0, sec, x, color)
		shape.color_all(1)
		draw()
	}else{
		ss = this_section(.5)
		i=-1 forsec sl {i+=1
			if (ss == this_section(.5)) {
				rvp[i].color(2)
			}else{
				rvp[i].color(1)
			}
		}
		g.flush()
	}
}

// should put this in plotshape class and avoid a meaningless point process
objectvar stim
proc shapemark() {local i
	if (numarg() == 1) {
		objectvar stim
		for i=0,$1-1 sec.sec stim = new PointProcessMark(x)	
		for i=0,$1-1 shape.point_mark(stim, color)
	}else{
		$o2.sec stim.loc($3)
	}
}
proc show_position() {local i, xx, min, x, xs, ys
	if ($1 == 2) {
		min = 1e9
		imin= -1
		xs = g.size(2) - g.size(1)
		ys = g.size(4) - g.size(3)
		i=-1 forsec sl {i+=1
			x = rvp[i].left()
			for (xx) {
				f = ((x + xx*L - $2)/xs)^2 + ((fun(xx) - $3)/ys)^2
				if (f < min) {
					min = f
					imin = i
				}
			}
		}
		shape.color_all(1)
		i=-1 forsec sl {i+=1
			if (i==imin) {
				rvp[i].color(2)
				shape.color(2)
			}else{
				rvp[i].color(1)
			}
		}
		g.flush()
		shape.flush()
	}
}

proc add_flush() {
        if (flush_) {
                sprint(tstr, "flush_list.append(%s)", this)
                execute(tstr)
        }
}
func view_count() {
	if (flush_) {
		return g.view_count()
	}else{
		return 0
	}
}
proc begin() {
}
proc flush() {
        draw()
}       
 
proc save() {}

endtemplate LogAvsX


proc makelogax() {
	if(!execute1("v", 0)) {
		continue_dialog("No accessed section: Can't start an LogAvsX")
		return
	}
	hoc_obj_[0] = new LogAvsX()
}