//
// Recording.hoc - Records activity traces in a binary format
//
// Variables and numbers are all recorded as double precision floats (8 bytes).
//
// Header is composed of the number of recorded retinal cells, then the number of recorded TC cells and finally the number 1 (there is only one cortical cell). 
// (See "StartBinaryRecording" function in this file)
//
// Then, for each time step (dt), in order:
// - for each recorded retinal cells (8 bytes)
//     write 1 if a spike was generated during this step, 0 otherwise
// - for each recorded thalamic cells (16 bytes)
//     write the Vm
//     write the number of input retinal spikes received during this step (sum of all spikes generated by all retinal cells converging to this TC cell)
// - for the cortical cell (16 bytes)
//     write the Vm
//     write the number of input thalamic spikes received during this step (sum of all spikes generated by all relay cells)
// (See "ProcessBinaryRecording" function in this file)
//
// In summary:
// - header size is 24 bytes
// - activity size is 40 bytes * number of steps
// - example for tstop = 10000 and dt = 0.1 (10s of activity at 10kHz)
//     40 bytes * 100001 steps => 4000040 bytes
//     adding header size, total generated file will be 4000064 bytes (~4MB)
//
// Thalamocortical convergence studies
// Sébastien Béhuret, UNIC/CNRS Paris, 2009
//

// Enabled in Simulation.hoc
RecordingEnabled = 0

// Unless you want to compare the generated traces in different cells, you should leave those to 1
// Will not record more than RetinalCellCount and RelayCellCount defined in Geometry.hoc
MaxRecordedRetinalCellCount = 1 //RetinalCellMax
MaxRecordedRelayCellCount = 1 //RelayCellMax

objref RecordingFile, RecordingVector
RecordingFile = new File()
RecordingVector = new Vector(1)

proc init() {
	finitialize(v_init)

	if (RecordingEnabled == 1) {
		ProcessRecording()
	}
}

proc advance() {
	fadvance()

	if (RecordingEnabled == 1) {
		ProcessRecording()
	}
}

proc StartRecording() {
	RecordingFile.wopen($s1)
	RecordingEnabled = 1
	StartBinaryRecording($s1)
}

proc ProcessRecording() {
	ProcessBinaryRecording()
}

proc StartBinaryRecording() {
	RecordedRetinalCellCount = RetinalCellCount
	if (RecordedRetinalCellCount > MaxRecordedRetinalCellCount) { RecordedRetinalCellCount = MaxRecordedRetinalCellCount }

	RecordedRelayCellCount = RelayCellCount
	if (RecordedRelayCellCount > MaxRecordedRelayCellCount) { RecordedRelayCellCount = MaxRecordedRelayCellCount }

	// header
	RecordingVector.x[0] = RecordedRetinalCellCount
	RecordingVector.fwrite(RecordingFile)

	RecordingVector.x[0] = RecordedRelayCellCount
	RecordingVector.fwrite(RecordingFile)

	RecordingVector.x[0] = 1
	RecordingVector.fwrite(RecordingFile)
}

proc ProcessBinaryRecording() { local i, RecordedRelayCellCount
	RecordedRetinalCellCount = RetinalCellCount
	if (RecordedRetinalCellCount > MaxRecordedRetinalCellCount) { RecordedRetinalCellCount = MaxRecordedRetinalCellCount }

	RecordedRelayCellCount = RelayCellCount
	if (RecordedRelayCellCount > MaxRecordedRelayCellCount) { RecordedRelayCellCount = MaxRecordedRelayCellCount }

	// Retinal spikes
	for i = 0, RecordedRetinalCellCount - 1 {
		RecordingVector.x[0] = RetinalCells[i].Spike
		RecordingVector.fwrite(RecordingFile)
	}

	// Relay Vms & summed inputs
	for i = 0, RecordedRelayCellCount - 1 {
		RecordingVector.x[0] = RelayCells[i].Soma.v(0.5)
		RecordingVector.fwrite(RecordingFile)

		Sum = 0
		for j = 0, RelayConvergenceCount - 1 {
			if (RelayAMPA[i][j].Trigger > RelayAMPA[i][j].Threshold) {
				Sum = Sum + RelayAMPA[i][j].Weight / RelayAMPAWeight
			}
		}
		RecordingVector.x[0] = Sum
		RecordingVector.fwrite(RecordingFile)
	}

	// Cortical Vm
	RecordingVector.x[0] = CorticalCell.Soma.v(0.5)
	RecordingVector.fwrite(RecordingFile)

	// Cortical summed input
	Sum = 0
	for i = 0, RelayCellCount - 1 {
		if (CorticalAMPA[i].Trigger > CorticalAMPA[i].Threshold) {
			Sum = Sum + 1
		}
	}
	RecordingVector.x[0] = Sum
	RecordingVector.fwrite(RecordingFile)
}

proc StopRecording() {
	RecordingEnabled = 0
	RecordingFile.close()
}

proc RecordingGUI() {
	xlabel("==============================")
	xlabel("recording")
	xlabel("==============================")
	xlabel("")
	xbutton("start", "StartRecording(\"Default.dat\")")
	xbutton("stop", "StopRecording()")
	xlabel("")
}