print "Loading writedata.hoc..."
// writedata.hoc
// Mark Rowan, School of Computer Science, University of Birmingham, UK
// March 2012
// Writes data in vit (and, possibly later, printlist and nqLFP) to disk
// periodically and flushes data from RAM, to enable very long simulations
// Data is stored in grvec format
// ***************************************************************************
// REQUIREMENTS:
// run.hoc should have SPKSZ at least large enough to hold all the spikes
// generated by the network in "buffertime" ms. With standard params, 15e3 ms
// produces around 25000 spikes in a one-column 940-cell model, so SPKSZ should
// be set to perhaps 35000.
//
// run.hoc should have the last line as prl(0,1) as currently printlist and
// nqLFP writing is not implemented, otherwise RAM usage will grow steadily as
// nqLFP / printlist object lists grow.
//
// params.hoc should have "declare("use_nqLFP",0)" to prevent massive nqLFP
// vectors being initialised within each cell in run.hoc:wrecon().
// ***************************************************************************
// Set frequency of write operations
declare("buffertime", 800e3) //16e3 // Write data to disk every buffertime ms of sim time
// Define objects
objref vitindexfile, vitdatafile // printlistvecfile, printlisttvecfile, nqLFPfile
strdef vitindexfilename, vitdatafilename // printlistvecfilename, printlisttvecfilename, nqLFPfilename
//strdef filepath // Needed if not passing filepath on the commandline. However, must be commented out if passing filepath on the commandline, or the supplied filepath will be overwritten by the strdef!
// Set up filenames
declare("filepath", "data") // Default save path (pass alternative paths to nrniv using '-c "filepath=..."' and ensure that 'strdef filepath' above is commented out)
sprint(vitindexfilename, "%s/%s", filepath, ".spks")
sprint(vitdatafilename, "%s/%s", filepath, "spks")
//sprint(printlistvecfilename, "%s%s%s", filepath, "printlist-vec", datetime)
//sprint(printlisttvecfilename, "%s%s%s", filepath, "printlist-tvec", datetime)
//sprint(nqLFPfilename, "%s%s%s", filepath, "nqLFP", datetime)
// Create files
vitindexfile = new File(vitindexfilename)
vitdatafile = new File(vitdatafilename)
//printlistvecfile = new File(printlistvecfilename)
//printlisttvecfile = new File(printlisttvecfilename)
//nqLFPfile = new File(nqLFPfilename)
proc writedata() { localobj vec
// Open files for appending
vitindexfile.aopen()
vitdatafile.aopen()
//printlistvecfile.aopen()
//printlisttvecfile.aopen()
//nqLFPfile.aopen()
// Debug printouts (comment out for extra speed during write operations):
printf("vit.vec has %d elements\n", vit.vec.size())
vec = vit.vec.where("!=", 0)
printf("writing %d elements\n", vec.size())
// Write vitem object to file using grvec format
// Can't just resize or delete/re-create Vectors, as the Vector pointers
// are held by intf6.mod and are not reset to zero (so after x elements are
// written and the Vector is resized, the next element will still be written
// index x rather than beginning again at index 0).
// Fortunately, intf6 provides a custom spike-to-file proc spkoutf:
col.ce.o(0).spkoutf(vitindexfile,vitdatafile) // print spike and time data to file
col.ce.o(0).spkoutf() // empty the spike data vectors and resize
// printlist contains vitem objects (just like vit) so we need to loop through
// printlist and write each object to file.
// Currently not implemented as this requires a similar mechanism to
// col.ce.o(0).spkoutf (above) but applied to the printlist objects.
// nqLFP also currently not implemented.
// Close files
vitindexfile.close()
vitdatafile.close()
//printlistvecfile.close()
//printlisttvecfile.close()
//nqLFPfile.close()
// Resize vit vectors to SPKSZ so they don't constantly shrink
vit.resize(SPKSZ)
// Empty each of the printlist and nqLFP vectors and reclaim memory
//prlclr() // Call prlclr() in run.hoc to clear printlist -- may also stop recording though?
//nqLFP.remove_all()
//wrecon() // Call wrecon() in run.hoc which reinitialises nqLFP. Is this correct?
// Put next data write event onto queue to occur after t + buffertime
cvode.event(t + buffertime,"writedata()")
}
//* seteventqueue - starts off the event queue
proc seteventqueue() {
// If mytstop is not a direct multiple of buffertime, then some data will remain
// unsaved at the end of the simulation. So we find the amount by which we bring
// forward the first write operation, so that the last write operation occurs at
// the same time as the end of the simulation, meaning that all data is saved.
// mytstop % buffertime ensures that we catch all the data
cvode.event(t + buffertime + (mytstop % buffertime),"writedata()")
}
declare("fith",new FInitializeHandler("seteventqueue()")) // Called as soon as INIT finishes