/************************************************************
'ca1' model code repository
Written by Marianne Bezaire, marianne.bezaire@gmail.com, www.mariannebezaire.com
In the lab of Ivan Soltesz, www.ivansolteszlab.org
Latest versions of this code are available online at:
ModelDB: 
Open Source Brain: http://www.opensourcebrain.org/projects/nc_ca1

Main code file: ../main.hoc
This file: Last updated on April 9, 2015

This file will create all the cells, set their position, initialize
some identifying parameters associated with their list if potential
synaptic inputs, and set aside some random number generators (random
streams) for each cell.
************************************************************/

proc createCells(){ local i, ij, si, pci, cellind, runresult, gid	// Create cells and assign a GID to each cell
	for cellind=0, numCellTypes-1 {									//	number stream have already been used
		for pcitr(&i, &ij, &gid, cellType[cellind].cellStartGid, cellType[cellind].cellEndGid) {// use the pciter over all cells of this type
			if (pc.gid_exists(gid)) {
				sprint(cmd, "{cellType[%g].CellList[%g]=new %s(%g,%g,%g)}", cellind, ij, cellType[cellind].technicalType, gid, i, cellind)
				{runresult=execute(cmd)} 						// This command was written as a string so
																//	the cell object doesn't have to be hard coded
																
				cells.append(cellType[cellind].CellList[ij])	// Append each cell to cells list
				
				cellType[cellind].numThisHost = ij+1 // set number of cells of this type on this host (but add 1 b/c ij is zero based)

				// Random streams: for more info, see the comments in ranstream.hoc
				// randomlist.append(new RandomStream(highIndex, lowIndex)
				// each cell can make use of three different random streams, specified with lowIndexes based on the cell's gid:
				//		lowIndex		Stream Name		Stream Purpose
				//		gid				n/a				Used in the fastconn/repeatconn mechanisms to determine which cells are connected
				//		gid + 1*ncell	ransynlist		Used in the connectivity hoc file to determine which synapses are used in each connection formed
				//		gid + 2*ncell	ranstimlist		Used in the stimulation hoc file (only by NetStims) to randomize the stimulation of the network
				//
				// Running independent simulations:
				//	Set the highIndex starting values using the RandomSeeds variable
				//	Make sure that simulations are independent of each other by checking that the beginning and end highIndex values
				//	 of each simulation DO NOT OVERLAP.
				//	The beginning highIndex value is always = 1+RandomSeeds.
				//	The max ending highIndex value used by each type of stream is printed in the MaxHighIndex.txt file.
				//	Consult the MaxHighIndex.txt file of a previous run, and then set RandomSeeds higher than any of its values,
				//	 to make your next run statistically independent
				//
				// To run the same network (same exact connections) under different stimulation conditions, only change RandomSeedsStim
				//  (the highIndex for ranstimlist). The behavioral experimental equivalent here would be to run the same mouse through
				//  multiple trials of a particular test.
				//
				// To run different networks (slightly different connections) under the same stimulation conditions, only change 
				//  RandomSeedsConn (the highIndex for ransynlist and the connectivity stream). The behavioral experimental equivalent 
				//  here would be to run different mice in the exact same behavioral test setup (an impossible ideal when you actually 
				//  think about all the confounding factors).

				ransynlist.append(new RandomStream(1+RandomSeedsConn, gid + 1*ncell)) 	// Create a new random number generator for each cell,
																						//	with a unique stream. This will be used to determine
																						//	what type of synapse is used in connections
																						
				ranwgtlist.append(new RandomStream(1+RandomSeedsConn, gid + 4*ncell)) 	// Create a new random number generator for each cell, used to 
																						//  set variable synapse weights

				ranstimlist.append(new RandomStream(1+RandomSeedsStim, gid + 2*ncell)) 	// Create a new random number generator for each cell, used by 
																						//  netstims for setting spont stim.
																						
				raninitlist.append(new RandomStream(1+RandomSeedsStim, gid + 3*ncell)) 	// Create a new random number generator for each cell, used to 
																						//  set variable initial voltage
																						
				ranlfplist.append(new RandomStream(1+RandomSeedsStim, gid + 4*ncell)) 	// Create a new random number generator for each cell, used to 
																						//  determine whether cell provides a small contribution to the
																						//  LFP calculation for cells outside of the region surrounding
																						//  the electrode point (see npole_lfp.hoc for more details).
																						
				cellType[cellind].CellList[ij].connect_pre(nil, nc)	// Create an empty connection for use by the spike detector
				pc.cell(gid, nc)									// Associate the cell with its gid and its spike generation location
				
				if (cellType[cellind].CellList[ij].is_art==0) {					// For realistic cells, assign position,
																				//  initialize synapse cid (cell id, aka
																				//  gid of postsynaptic cell)
																				
					for si=0, cellType[cellind].CellList[ij].pre_list.count-1 {	// Iterate over each pre cell type's synapse list
						for j=0, cellType[cellind].CellList[ij].pre_list.o(si).count-1 {	// Iterate through each synapse in the list
							cellType[cellind].CellList[ij].pre_list.o(si).o(j).cid=gid		// Set the cell id (cid) for each synapse
																							//  Note that the synapse id (sid) has already
																							//  been set within the individual cell template,
																							//  as it corresponds to the synapse type in 
																							//  terms of the postsynaptic cell's list of
																							//  potential synapses) 
																							//  Note: cid and sid parameters were added to
																							//  MyExp2Syn, a custom version of the Exp2Syn
																							//  mechanism
						}
					}

					// If the user has set the PrintTerminal parameter very high to get lots
					//  of printouts, print out a notification when every tenth of each cell
					//  type has been created.
					if ((ij%int(cellType[cellind].numCells/10+1) == 0) && (PrintTerminal>2)) {
						print cellType[cellind].cellType_string, ": ", i
					}
				}				
				
				// Determine the z height of the cells of this type by finding which layer they are in and
				//  adding the heights of all the lower layers to get the height in the current layer
				addheight=0
				if (cellType[cellind].layerflag>0) {addheight=LayerVector.sum(0,cellType[cellind].layerflag-1)}

				// Algorithmically generate cell position using the functions get_x_pos, get_y_pos, and get_z_pos,
				//  defined in the mod file ../positionfcns.mod
				if (gid==20900) {
					print "TROUBLESHOOT POSITIONING"
					print "gid=", gid
					print "cellType[cellind].cellStartGid=", cellType[cellind].cellStartGid
					print "cellType[cellind].dentateXBins=", cellType[cellind].dentateXBins
					print "cellType[cellind].dentateYBins=", cellType[cellind].dentateYBins
					print "cellType[cellind].dentateZBins=", cellType[cellind].dentateZBins
					print "cellType[cellind].dentateXBinSize=", cellType[cellind].dentateXBinSize
					print "cellType[cellind].dentateYBinSize=", cellType[cellind].dentateYBinSize
					print "cellType[cellind].dentateZBinSize=", cellType[cellind].dentateZBinSize
					print "addheight=", addheight
				}
				xpos=get_x_pos(gid,cellType[cellind].cellStartGid,cellType[cellind].dentateXBins,cellType[cellind].dentateYBins*cellType[cellind].dentateZBins,cellType[cellind].dentateXBinSize)
				ypos=get_y_pos(gid,cellType[cellind].cellStartGid,cellType[cellind].dentateYBins,cellType[cellind].dentateZBins,cellType[cellind].dentateYBinSize)
				zpos=get_z_pos(gid,cellType[cellind].cellStartGid,cellType[cellind].dentateZBins,cellType[cellind].dentateZBinSize,addheight)	
				
				cellType[cellind].CellList[ij].position(xpos,ypos,zpos)		// Record cell position in cell object
								
			}
		} 
	}

	nc = nil // Then clear the reference to the netcon object, which should destroy the netcon (because all refs would have been removed)
	if  (PrintTerminal>1) {print "Host ", pc.id, " created cells."}
}
createCells()