parmfitness_generator_append("MulRunFitter")

begintemplate MulRunFitter
public p, vbox, save, version, map, unmap, showopt, opt, prun
public wfile, rfile, efun, build, title, chtitle
public optsave, optrestore
external object_index
strdef tstr, title, basename_
objref p, vbox, this, fspec, fdat, opt, optbox, nil, tobj, sf, optimizer

proc init() {
	running = 0
	sf = new StringFunctions()
	ranfac = 2
	id = object_index(this) + 1
	fspec = new File("temp.ft1")
	fdat = new File("temp.fd1")
	version_ = 6
	title = "Unnamed multiple run protocol"
	p = new ParmFitnessGui(new ParmFitness(title),this)
	opt = new OptimizerWrap(p.pf)
	opt.set_optimizer("MulfitPraxWrap")
	if (numarg() == 0) {
		build()
		map()
	}else if($1 == 0) {
		build(0)	// this is slave so don't ref by vbox
	}
}

proc chtitle() {
	title = $s1
	p.pf.title = $s1
}

func version() {
	if ($1 > version_) {
		printf("MulrunFitter data format version %d is incompatible with this version %d tool\n",\
 			$1, version_)
		stop
		return 0
	}
	return 1
}

func efun() {
	opt.prun()
	return opt.minerr
}

proc map() {
	sprint(tstr, "%s", this)
	if (numarg() > 0) {
		vbox.map(tstr, $2, $3, $4, $5)
	}else{
		vbox.map(tstr)
	}
}

proc unref() {
	if ($1 == 1) {
		objref p
	}
}

proc unmap() {
	p.dact()
	objref optbox, opt
	vbox.unmap
}

proc build() {
	vbox = new VBox(3)
	vbox.priority(100)
	vbox.save("save()")
	if (numarg() == 0) {
		vbox.ref(this)
	}
	vbox.dismiss_action("unmap()")
	vbox.intercept(1)
	p.map()
	vbox.intercept(0)
}

proc showopt() {
	optbox = new VBox()
	optbox.save("")
	optbox.intercept(1)
	xpanel("")
	xpvalue("Real time", &opt.time)
	xpvalue("# multiple runs", &opt.nefun)
	xpvalue("Minimum so far", &opt.minerr)
	xpvalue("Randomize with factor", &ranfac, 1, "randomize()")
	xcheckbox("Append the path to savepath.fit", &opt.saveflag)
	xcheckbox("Running", &running, "running = !running")
	xbutton("Stop", "stoprun = 1")
	xbutton("Optimize", "prun()")
	if (p.pf.pc.nhost > 1) {
		xbutton("|| Optimize", "paropt()")
	}
	xpanel()
	xpanel("")
	opt.showopt()
	xpanel()
	optbox.intercept(0)
	sprint(tstr, "%s Optimize", this)
	if (numarg() > 3) {
		optbox.map(tstr, $1, $2, $3, $4)
	}else{
		optbox.map(tstr)
	}
}

proc prun() {
	if (running){
		if (boolean_dialog("Running flag is on.", "Turn it off", "Keep it on")){
			running = 0
		}
	}
	stoprun = 0
	running = 1
	opt.prun()
	running = 0
}

proc paropt() {
	p.pf.use_parallel(1)
	opt.prun()
	p.pf.use_parallel(0)
}

proc randomize() { p.pf.randomize(ranfac) }


proc rfile() {
	$o1.gets($s3)
	p.pf.rfile($o1, $o2, $s3)
}
proc wfile() {
	$o1.printf("MulRunFitter: %s\n", title)
	p.pf.wfile($o1, $o2)
}

proc basename() {local i
	i = sf.tail($s1, ".*[/:\\]", basename_)
	if (i == -1) {
		basename_ = $s1
	}	
}

proc read_data() {
	if (!fspec.ropen()) {
		fspec.getname(tstr)
		printf("missing MulRunFit spec file: %s\n", tstr)
	}
	if (!fdat.ropen()) {
		fdat.getname(tstr)
		printf("missing MulRunFit data file: %s\n", tstr)
		return
	}
	p.pf.rfile(fspec, fdat)
	fspec.close fdat.close
}

proc save_data() {
	fspec.wopen()
	fdat.wopen()
	p.pf.wfile(fspec, fdat)
	fspec.close fdat.close
}

proc save() {
	vbox.save("load_file(\"mulfit.hoc\", \"MulRunFitter\")\n}\n{")
	vbox.save("ocbox_ = new MulRunFitter(1)")
	vbox.save("}\n{object_push(ocbox_)}\n{")
	sprint(tstr, "version(%d)", version_)
	vbox.save(tstr)
	sprint(tstr, "ranfac = %g", ranfac)
	vbox.save(tstr)
	
	vbox.save(tstr, 1) // get name of session file
	sprint(tstr, "%s.ft%d", tstr, id)
	fspec = new File(tstr)
	vbox.save(tstr, 1) // get name of session file
	sprint(tstr, "%s.fd%d", tstr, id)
	fdat = new File(tstr)
	save_data()
	fspec.getname(tstr)
	basename(tstr)	// assume session retrieved with load_file
	sprint(tstr, "fspec = new File(\"%s\")", basename_)
	vbox.save(tstr)
	fdat.getname(tstr)
	basename(tstr)
	sprint(tstr, "fdat = new File(\"%s\")", basename_)
	vbox.save(tstr)
	vbox.save("read_data()")
	vbox.save("build()")
	vbox.save("}")
	tobj = new Vector(4)
	opt.save_optimizer(vbox)
	p.mapsave(vbox, tobj)
	optsave(vbox, tobj)

	vbox.save("{object_pop()}\n{")
}

proc optsave() {
	if (object_id(optbox)) if (optbox.ismapped) {
		$o2.resize(4)
		optbox.size(&$o2.x[0])
		sprint(tstr, "{optrestore(%g, %g, %g, %g)}", $o2.x[0], $o2.x[1], $o2.x[2], $o2.x[3])
		$o1.save(tstr)
	}
}
proc optrestore() {
	showopt($1, $2, $3, $4)
}

endtemplate MulRunFitter
