I took your last suggestion and created a custom function for logging data after each run. It appears to be working well after resolving some errors along the way. Posting it here for your confirmation and in case it would be handy for anyone else:
optwrap.hoc needs to be updated to:
Code: Select all
begintemplate OptimizerWrap
external classname, mulfit_optimizers_, mulfit_optimizer_names_
// public functions
public prun, set_optimizer, save_optimizer, optwrap_efun, showopt
// public variables
public saveflag, start, nquad, wfile, optimizer, opt_index, minerr, nefun, time
objref savepath, tl, pf, tobj, opt, this, start, optimizer
strdef tstr
proc init() {
pf = $o1
start = new Vector()
savepath = new File()
nefun = 0
st = startsw()
time = 0
currenterr = 1e9
saveflag = 0
e = 0
}
proc set_optimizer() {
for i=0, mulfit_optimizers_.count-1 { // need to know index too
if (!strcmp(mulfit_optimizers_.object(i).s, $s1)) {
opt_index = i
}
}
sprint(tstr, "optimizer = new %s(pf)", $s1)
execute(tstr, this)
}
//--------------------------------------------------------------
objref saveDataPath
//Function for logging data after each run into a temporary file
proc saveTempFile() {
if (saveflag) {
saveDataPath = new File() //Added
saveDataPath.wopen("savepath_complete.tmp")
}
}
proc mySaveData() {
if (saveDataPath.isopen) {
saveDataPath.printf("%d %d %-12.8g ", nefun, time, minerr)
saveval_modified()
}
}
//Saves the current parameter set
proc saveval_modified() {
if (numarg() == 1) saveDataPath.printf("%s", $s1)
tl = pf.parmlist
for i=0, tl.count-1 {
saveDataPath.printf("%-12.8g ", tl.object(i).val)
}
saveDataPath.printf("\n")
}
//Creates final output file
proc saveFile() {
if (saveDataPath.isopen) {
saveDataPath.close
saveDataPath.aopen("savepath_complete.fit")
saveDataPath.printf("start\n")
saveDataPath.close
system("cat savepath_complete.tmp >> savepath_complete.fit")
}
}
//--------------------------------------------------------------
func optwrap_efun() {local i
nefun += 1
e = pf.efun($1, &$&2)
if (!stoprun) {
if (minerr == -1 || e < minerr) {
minerr = e
}
}
//--------------------------------------------------------------
//Function call to save data after each run
if (saveflag) {
mySaveData()
}
//--------------------------------------------------------------
doNotify()
time = startsw() - st
return e
}
proc saveval() {
if (numarg() == 1) savepath.printf("%s", $s1)
tl = pf.parmlist
for i=0, tl.count-1 {
savepath.printf("%-12.8g ", tl.object(i).val)
}
savepath.printf("\n")
}
func prun() {
//--------------------------------------------------------------
//Call to create temporary log file
if (saveflag) {
saveTempFile()
}
//--------------------------------------------------------------
nefun = 0
minerr = -1
pf.doarg_get(start)
nquad = 0
if (start.size == 0) {
minerr = pf.efun(0, &time) // time is dummy here
}else{
minerr = optwrap_efun(start.size, &start.x[0])
if (stoprun) {return minerr}
st = startsw()
time = startsw() - st
minerr = optimizer.prun(this)
time = startsw() - st
minerr = optwrap_efun(start.size, &start.x[0])
}
//--------------------------------------------------------------
//Call to create final output file
if (saveflag) {
saveFile()
}
//--------------------------------------------------------------
return minerr
}
proc showopt() {
sprint(tstr, "%s specific items", mulfit_optimizer_names_.object(opt_index).s)
xlabel(tstr)
optimizer.showopt()
}
strdef opt_class
proc save_optimizer() { localobj vbox
vbox = $o1
classname(optimizer, opt_class)
// set the optimizer than let it save itself
sprint(tstr, "opt.set_optimizer(\"%s\")", mulfit_optimizers_.object(opt_index).s)
vbox.save(tstr)
vbox.save("{object_push(opt.optimizer)}")
vbox.save("{")
optimizer.save_optimizer(vbox)
vbox.save("}")
vbox.save("{object_pop()}")
}
endtemplate OptimizerWrap
(The additions have been enclosed within dividers - 4 segments)
With the above changes we would get:
> Default "savepath.fit" that MRF provides
> An additional file named "savepath_complete.fit" with data from each simulation run
The implementation is quite similar to the original. The data is saved in the following format:
Line 1: start (just a label)
Line 2 onwards: (data)
- Column 1: Simulation Run Number
- Column 2: Time (s)
- Column 3: Error Value
- Columns 4+: Parameter Values