// Maurice Petroccine, SUNY Albany (mpetroccione@albany.edu)
// Last updated on 11/29/2021

// This code applies generates timing for the excitatory and inhibitory inputs in our model as output files.
// The simulation needs to generate the timing files prior to running the E-I_Frequency models and the in this folder.
// File will appear in the same folder as the hoc file after it is done (make sure simulation is finished before opening).
// This code should be executed by typing either go(WT) or go(KO)
// Necessary files needed to run: 

load_file ("nrngui.hoc")
load_file ("ranstream.hoc")

strdef preface, dirstr
preface = "."

freq_step = 5																// Hz,. size of the frequency step

NSNUM = 200 																// how many NetStims are to be created - used as separate random timing values
MAXSTREAM = 10000 															// max # events in a NetStim's stream before it begins to repeat values already generated by a different stream.
																			// set to 0 and all NetStims will produce identical streams
tstop = 4000 																// length of simulation NOTE: this value along with the frequency will determine the number of stimulation times produced

ISI = 1000 																	// default NetStim parameters - will be overwritten
NUM = 210
START = 50
NOISE = 0

/***** INSTRUMENTATION *****/

objref nslist, rslist														// create two lists to store the random timestamps for initiation 
nslist = new List()
rslist = new List()

objref  nc[NUM], nc2[NUM], nc3[NUM]

proc makenetstims() { local i  localobj ns, rs								// make netstims
	nslist = new List()
	rslist = new List()
	random_stream_offset_ = MAXSTREAM*4										// offsets selections from the list of randomly generated values so they don't overlap
	for i = 0, $1-1 {
		ns = new NetStim()													// creates a new NetStim
		nslist.append(ns)													// appends the NetStim to nslist
		rs = new RandomStream(NSNUM+i)										// creates a random stream
		rslist.append(rs)													// appends teh values to rs
		ns.noiseFromRandom(rs.r)											// applies the noise from the ransom stream to ns
		rs.r.negexp(1) 														// must specify negexp distribution with mean = 1
		rs.start()
	}
}

l = 0
objref tvec, nil
	tvec = new Vector(100)
objref tfil	
	tfil = new File()
strdef tmpstr

proc setparams() { local i													// protocol to assign all netstims default parameters
	for i = 0,nslist.count()-1 {										
		nslist.o(i).interval = ISI
		nslist.o(i).number = NUM
		nslist.o(i).start = 100000											// by default all netstims start at 100 sec (after the simulation ends)
		nslist.o(i).noise = 1
	}
}

proc gen_times() {localobj nct
	tvec.resize(0)															// clears the values from the previous interation
	nct = new NetCon(nslist.o(l+100), nil)									// selects the 
	nct.record(tvec)														// records the timing of each netcon activation to be used in the other simulation
	run()
	nct.record(tvec)
}
	
proc xytofile() { local b													// procedure to write stimulation times to output files 
	w=0
	print "writing to ", $s2												// notifies when writing to file
	for b=0,$o1.size()-1 {tfil.printf("%g\n", tvec.x[b])}					// prints each time on a new line
 }
 
proc go(){ local i															// procedure to execute this hoc file, should be executed with either go(WT) or go(KO)
	for i = 0, 100 {
		makenetstims(NSNUM)
		for l = 0, nslist.count()-101 {
			setparams()
			nslist.o(l+100).start = 50										// sets stimulation start to 50 ms
			nslist.o(l+100).interval = 1000/(i*5+5)							// sets the mean interval to increment in steps of 5 Hz
			sprint(tmpstr, "%s%dHZ_ex_times_%d.dat", $s1, (i*5+5), l)		// creates a filename based on the mean frequency of the stimulation
			tfil.wopen(tmpstr)												// creates the output file
			gen_times()														// generates the timestamps for stimulation
			xytofile(tvec, tmpstr)											// writes to the output file
			tfil.close()													// closes the output file
		}
	}
}