// nFit
// (c) Charles CH Cohen, 2014-present
// this software is released to the public under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 
// International license (CC BY-NC-ND 4.0, in English).
// for any questions, please email c.cohen@gmx.com



// -------------------------------Variables----------------------------------------
objref stim, stimbox, stimvec

strdef tokstim, locstim, sublocstim, strstimc, secstim
// --------------------------------------------------------------------------------



// -------------------------------seticlamp----------------------------------------
// takes either four arguments: (1) locstim, i.e. loc[arraynum](subloc); (2) iamp; 
// (3) idel; (4) idur, or one argument: stimvec (see getstimvec). 
// creates iclamp at locstim with given parameters.
proc seticlamp() {local k, iamp, idel, idur

	if (!numarg()) {

		// last setup
		// only one file at a time...
		k = 0		
		while (k < 4) {

			if (!getfile.isopen) {

				if (k == 0) {

					getstring(ses, locstimfilestr, locstim)
					k += 1
				
				} else if (k == 1) {
				
					iamp = getvarp(ses, iampfilestr)
					k += 1
				
				} else if (k == 2) {

					idel = getvarp(ses, idelfilestr)
					k += 1
				
				} else if (k == 3) {

					idur = getvarp(ses, idurfilestr)					
					k += 1
				}
			}
		}
	
	} else if (numarg() == 4) {

		// must provide all four arguments
		sprint(locstim, $s1)
		iamp = $2
		idel = $3
		idur = $4
	}

	sprint(strstimc, "%s%s%s%g%s", "access ", locstim, " stim = new IClamp(", getsubloc(locstim), ")")
	execute(strstimc)
	
	{stim.amp = iamp stim.del = idel stim.dur = idur}

	if (numarg() != 1) printclamp()

	strf.head(locstim, "[(]", secstim)

	// writebit(ses, "resetbit.dat", 0)
}
// --------------------------------------------------------------------------------



// -------------------------------printclamp---------------------------------------
proc printclamp() {

	print "IClamp set at ", locstim
	print "Amplitude: ", stim.amp*1000, "pA"
	print "Duration: ", stim.dur, "ms"
	print "Delay: ", stim.del, "ms"
}
// --------------------------------------------------------------------------------



// -----------------------------getiampind-----------------------------------------
func getiampind() {

	if (numarg() == 1 && argtype(1) == 2) {

		if (!strcmp($s1, "help")) {

			print "Enter:"
			print "1) injection amplitude of interest (nA)"
			print "output: that address within iampvec (required for getiampdir()), if it exists. Else -1."
			stop
		}
	}


	if (iampvec.contains($1)) {

		return iampvec.indwhere("==", $1)
	
	} else {

		return -1
	}
}
// --------------------------------------------------------------------------------



// -------------------------------reseticlamp--------------------------------------
// takes (1) iamp and optional (2) whether parallel optimizations (0 or 1).
// resets iclamp with iamp given seticlamp (locstim, idel and idur)
proc reseticlamp() {local wstart, wkill, win, interval, wcount
	
	{stim.amp = $2}
	writenum(ses, iampfilestr, $2)
	writebit(ses, iiampfilestr, $1)
	printclamp()

	if (has_data) {
	
		changedata($1)
		tol = settol($1)
		maxstepsize = setmaxstepsize(tol)
		writefitdata($1)
	}

	// window replacement is best for GUI-based model exploration. Otherwise, 
	// substantial slowdown occurs with every cycle of window replacement.
	// if (!para) {
		
	// 	wstart = 3
	// 	wkill = 2+nf
	// 	win = wstart + getvar(ses, "resetbit.dat") * (PWM.count - wstart - wkill)
	// 	sprint(wstr, "%s%d%s", "PWM.close(", win, ")")
	// 	timer = new Timer(wstr)
	// 	interval = 0.2
	// 	timer.seconds(interval)
	// 	PWM.close(win)
	// 	wcount = win
		
	// 	while (wcount <= win+nf+1) {
	// 		timer.start()
	// 		wcount += 1
	// 	}
	// 	timer.end()

	// 	while (wcount <= win+nf+2) {
		
	// 		if (wcount > win+nf+1) {	

	// 			writevtplot(mode, stim.amp)
	// 			writevxplot(mode, stim.amp)
	// 			writeshape(mode, stim.amp)

	// 			if (mode == 0) {
					
	// 				loadfile(1, ses, "vtplot-pas.ses")
	// 				loadfile(1, ses, "vxplot-pas.ses")
	// 				loadfile(1, ses, "shapeplot-pas.ses")

	// 			} else if (mode == 1) {

	// 				loadfile(1, ses, "vtplot-act.ses")
	// 				loadfile(1, ses, "vxplot-act.ses")
	// 				loadfile(1, ses, "shapeplot-act.ses")					
	// 			}

	// 			writebit(ses, "resetbit.dat", 1)

	// 			wcount = win+nf+3
	// 		}
	// 	}
		
	// 	wstr = ""
	// }
}
// --------------------------------------------------------------------------------



// ------------------------------changeiclamp--------------------------------------
proc changeiclamp() {local k, newiamp, newidur, newidel

	mode = getvar(ses, "mode.dat")
	setfilestr(mode, has_data)

	getstring(ses, locstimfilestr, locstim)
	sprint(stimstr, locstim)
	k = string_dialog("Please enter stimulus section. Example: axon[0](0.5)", stimstr)
	if (k) sprint(stimstr, stimstr)

	sprint(ampstr, "%g", newiamp = getvarp(ses, iampfilestr))
	k = string_dialog("Please enter stimulus amplitude (nA)", ampstr)
	if (k) {

		sprint(ampstr, ampstr)
		sscanf(ampstr, "%lf", &newiamp)
	}

	sprint(durstr, "%g", newidur = getvarp(ses, idurfilestr))
	k = string_dialog("Please enter stimulus duration (ms)", durstr)
	if (k) {

		sprint(durstr, durstr)
		sscanf(durstr, "%lf", &newidur)
	}

	sprint(delstr, "%g", newidel = getvarp(ses, idelfilestr))
	k = string_dialog("Please enter delay to stimulus start (ms)", delstr)
	if (k) {

		sprint(delstr, delstr)
		sscanf(delstr, "%lf", &newidel)
	}

	seticlamp(stimstr, newiamp, newidel, newidur)
	saveiclamp(mode)
}
// --------------------------------------------------------------------------------



// ------------------------------saveiclamp----------------------------------------
proc saveiclamp() {local tempnum
	
	setfilestr($1, has_data)

	writestring(ses, locstimfilestr, locstim)
	writenum(ses, iampfilestr, stim.amp)
	writenum(ses, idelfilestr, stim.del)
	writenum(ses, idurfilestr, stim.dur)

	if (has_data) {

		if (tempnum = iampvec.indwhere("==", stim.amp) != -1) {

			writebit(ses, iiampfilestr, tempnum)

		} else {

			writebit(ses, iiampfilestr, 0)			
		}
	}
}
// --------------------------------------------------------------------------------



// -------------------------------setstimpanel-------------------------------------
proc setstimpanel() {local k

	stimbox = new VBox(3)
	stimbox.intercept(1)
	xpanel("")
	
	xlabel("starting IClamp:")
	
	sprint(tempstr, "%s%s", "Location: ", locstim)
	xlabel(tempstr)
	if (stim.amp >= 0) {
		sprint(tempstr, "%s%g%s", "+", setnsig(stim.amp, 5)*1000, " pA")
	} else {
		sprint(tempstr, "%g%s", setnsig(stim.amp, 5)*1000, " pA")
	}
	sprint(tempstr, "%s%s", "Amplitude: ", tempstr)
	xlabel(tempstr)
	sprint(tempstr, "%s%g%s", "Duration: ", setnsig(stim.dur, 5), " ms")
	xlabel(tempstr)
	sprint(tempstr, "%s%g%s", "Delay to injection: ", setnsig(stim.del, 5), " ms")
	xlabel(tempstr)
	xpanel()
	
	xpanel("")
	xlabel("Change injection amplitude to:")
	for k = 0, iampvec.size-1 {
		
		if (iampvec.x[k] > float_epsilon) {
			sprint(tempstr, "%s%g%s", "+", setnsig(iampvec.x[k], 3)*1000, " pA")
		} else if (iampvec.x[k] < -float_epsilon) {
			sprint(tempstr, "%g%s", setnsig(iampvec.x[k], 3)*1000, " pA")
		} else {
			sprint(tempstr, "%g%s", setnsig(iampvec.x[k], 3)*1000, " pA")
		}

		sprint(stimstr, "%s%g%s%.11le%s", "reseticlamp(", k, ", ", iampvec.x[k], ")")

		xradiobutton(tempstr, stimstr)
	}
	xpanel()

	xpanel("")
	xbutton("change stim location, amp, dur or del", "changeiclamp()")
	xpanel()
	
	xpanel("")
	xpanel()

	stimbox.intercept(0)

	// x, y, w, h
	// x = 54
	// y = 512
	// w = 269.76
	// h = variable: 
	// minimum h: 206.4
	// afterwards, for each current injection amplitude, add 15.36
	
	stimbox.map("Set IClamp", 54, 512, 269.76, 206.4+iampvec.size*15.36)
}
// --------------------------------------------------------------------------------