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