begintemplate ImpedanceRatio
public measure, inject, ratio, input, transfer, fmin, fmax, extended,fres, logf, rads
public box, move, imp, style, pl, shape, flush, view_count, begin
objectvar imp, sec[2], shape, b1, this, move_callback
objectvar g, imp, box, pbox
double x[2], color[2]
strdef s0, s1, stemp, sdist, fstyle, tstr, ipstyle, tpstyle
// kludge to use graphline() in pl()
f = 0
proc init() {
extended = 0
deltafac = 0.001
fres = 1
fmin = 0.01
fmax = 100
logf = 0
style_ = 1
rads = 0
ipstyle = "Input Phase (deg)"
tpstyle = "Transfer Phase (deg)"
fstyle = "log(Attenuation)"
mark_ = 1
flush_ = 0
scale_ = 1
measure(0.5)
inject(0.5)
imp = new Impedance()
build()
doNotify()
style(style_)
// scale_ = 1
// pl()
// scale_ = 0
}
proc build(){
dist()
box = new VBox()
box.ref(this)
box.save("")
box.intercept(1)
xpanel("", 1)
xbutton("Redraw", "pl()")
xmenu("SelectLocation")
xradiobutton("Select Measure", "mark_=0")
xradiobutton("Select Inject", "mark_=1", 1)
xbutton("Swap Measure/Inject", "exchange()")
xmenu()
xmenu("Plot")
xradiobutton("log(Attenuation)", "style(0)")
xradiobutton("Zin (Mohm)", "style(1)", 1)
xradiobutton("Ztransfer (Mohm)", "style(2)")
xradiobutton("V(measure)/V(inject)", "style(3)")
xradiobutton(ipstyle, "style(4)")
xradiobutton(tpstyle, "style(5)")
xmenu()
xmenu("Extras")
xstatebutton("Movie mode", &flush_, "add_flush()")
xstatebutton("Auto Scale", &scale_, "pl()")
xbutton("Parameters", "parm()")
xmenu()
xpanel()
xpanel("")
xcheckbox("include dstate/dt contribution", &extended, "pl()")
xvarlabel(s0)
xvarlabel(s1)
xvarlabel(sdist)
xpanel()
shape = new Shape()
for i=0,1 color[i]=i+2
shapemark(2)
for i=0,1 {
color[i] = i+2 // red, blue
shapemark(i, sec[i], x[i], color[i])
}
shape.action("move()")
defgraph()
box.intercept(0)
sprint(tstr, "%s Impedance vs Frequency", this)
box.map(tstr)
}
proc parm() {
pbox = new VBox()
pbox.save("")
pbox.intercept(1)
xpanel("")
xlabel("x axis scale (press redraw after changes)")
xpvalue("fmin", &fmin, 2)
xpvalue("fmax", &fmax, 2)
if (logf == 1) {
xpvalue("x resolution (log10 Hz)", &fres, 2)
} else {
xpvalue("x resolution (Hz)", &fres, 2)
}
xcheckbox("Use logarithmic axis", &logf, "logfchange()")
xlabel("")
xcheckbox("Phase in radians", &rads, "setpstyle()")
xlabel("")
xlabel("dy for df/dy calculation of extended y' = f(y)")
xpvalue("delta factor", &deltafac, 2, "imp.deltafac(deltafac)")
xpanel()
pbox.intercept(0)
sprint(tstr, "Params for %s", this)
pbox.map(tstr)
}
proc logfchange() {
if (logf == 1) {
fres = log10(fres)
if (fmin<0.01) fmin=-2 else fmin = log10(fmin)
fmax = log10(fmax)
if (fres<=0) fres=0.05
} else {
fres = 10^fres
fmin = 10^fmin
fmax = 10^fmax
}
style(style_)
}
proc setpstyle() {
if (rads==0) {
ipstyle = "Input Phase (deg)"
tpstyle = "Transfer Phase (deg)"
} else {
ipstyle = "Input Phase (rad)"
tpstyle = "Transfer Phase (rad)"
}
style(style_)
}
proc defgraph() {
g = new Graph()
g.size(0,fmax,0,1)
style(style_)
}
proc style() {
style_ = $1
g.erase_all()
g.label(-100, -100, "")
if ($1 == 0) {
g.addexpr("-log(ratio(f))")
label("log(Attenuation)")
}else if ($1 == 1) {
g.addexpr("input(f)")
label("Zin (Mohm)")
}else if ($1 == 2) {
g.addexpr("transfer(f)")
label("Ztransfer (Mohm)")
}else if ($1 == 3) {
g.addexpr("ratio(f)")
label("V(measure)/V(inject)")
} else if ($1 == 4) {
g.addexpr("input_phase(f)")
label(ipstyle)
} else if ($1 == 5) {
g.addexpr("transfer_phase(f)")
label(tpstyle)
}
sec[0].sec measure(x[0])
sec[1].sec inject(x[1])
pl()
}
proc label() {
if (logf == 0) {
g.label(.5, .9, "freq (Hz)")
} else {
g.label(.5, .9, "freq log10(Hz)")
}
g.label($s1)
}
proc move() {local i, xx
i = mark_
xx = hoc_ac_
if (i == 0) {
measure(xx)
}else{
inject(xx)
}
shapemark(i, sec[i], x[i], color[i])
dist()
pl()
}
//objectvar etmp
proc exchange() {local xx, i localobj etmp //swap inject and measure
etmp = sec[0]
xx = x[0]
sec[1].sec measure(x[1])
etmp.sec inject(xx)
// objectvar etmp
for i=0,1 shapemark(i, sec[i], x[i], color[i])
pl()
}
double sz[4]
proc pl() {local max, x, val
g.begin()
for (x=fmin; x <= fmax; x=x+fres) {
if (logf == 0) {
f = x
} else {
f = 10^x
}
g.plot(x)
}
if (scale_) {
g.size(&sz[0])
g.size(fmin, fmax, sz[2], sz[3])
}
g.flush()
}
proc measure() {
sec[0] = new SectionRef()
x[0] = $1
sectionname(stemp)
if (style_ == 1) {
sprint(s0, "unused (red): %s(%g)", stemp, $1)
}else if (style_ == 4) {
sprint(s0, "unused (red): %s(%g)", stemp, $1)
}else{
sprint(s0, "measure (red): %s(%g)", stemp, $1)
}
}
proc inject() {
sec[1] = new SectionRef()
x[1] = $1
sectionname(stemp)
if (style_ == 1) {
sprint(s1, "measure/inject (blue): %s(%g)", stemp, $1)
} else if (style_ == 4) {
sprint(s1, "measure/inject (blue): %s(%g)", stemp, $1)
}else{
sprint(s1, "inject (blue): %s(%g)", stemp, $1)
}
}
func ratio() {local y
compute($1)
sec[1].sec y = imp.ratio(x[1])
return y
}
func transfer() {local y
compute($1)
sec[1].sec y = imp.transfer(x[1]) // since v(x)/i(loc) == v(loc)/i(x)
return y
}
func input() {local y
compute($1)
sec[1].sec y = imp.input(x[1])
return y
}
func input_phase() {local y
compute($1)
sec[1].sec y = imp.input_phase(x[1])
if (rads == 0) y=y/PI*180
return y
}
func transfer_phase() {local y
compute($1)
sec[1].sec y = imp.transfer_phase(x[1])
if (rads == 0) y=y/PI*180
return y
}
proc compute() {
sec[0].sec imp.loc(x[0])
imp.compute($1, extended)
}
objectvar rvp
proc dist() {local y
sec[0].sec distance(0,x[0])
sec[1].sec y = distance(x[1])
sprint(sdist, "distance(um) %g", y)
}
// should put this in plotshape class and avoid a meaningless point process
objectvar stim[1]
proc shapemark() {local i
if (numarg() == 1) {
objectvar stim[$1]
for i=0,1 sec[i].sec stim[i] = new PointProcessMark(x[i])
for i=0,1 shape.point_mark(stim[i], color[i])
}else{
$o2.sec stim[$1].loc($3)
}
}
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() {
pl()
}
proc save() {}
endtemplate ImpedanceRatio
proc makeImpRatio() {
if(!execute1("v", 0)) {
continue_dialog("No accessed section: Can't start an ImpedanceRatio")
return
}
hoc_obj_[0] = new ImpedanceRatio()
objref hoc_obj_[2]
}