Auto save upon computer shutdown

Hello! I am wondering if there is a way to enable auto save option to igor files for recovery upon PC shutdown/restart? I have lost my files many a times and it would be great if someone could share the steps to enable auto save option.

Thank you!

I don't know of any built-in options. It seems to me like the best approach would be to have Igor save periodically on its own. (Because a computer shutdown might not provide enough time for Igor to save anyway.) 

I sometimes use the code below to make sure my experiments save every so often, but I haven't tested it that much. It could be modified to save a copy instead of overwriting the pre-existing pxp file. 

As to handling an unexpected computer shutdown, I wonder if IgorBeforeQuitHook (displayhelptopic "Used-defined hook functions") with the SaveExperiment function could help. 

All of these home-made options require the code to be compiled, which is a downside.

Editing to add: another downside to this approach is that it does not save items in the Igor instance that are saved in separate files (e.g., in some cases, Notebooks and procedure files). (I also changed the code below to make it an independent module, which seems a good idea.)

 

#pragma IndependentModule = AutosaveModule          //allows these functions to run while procedures are uncompiled

//EXPERIMENT AUTO SAVE FUNCTIONS
//default is that auto save begins on experiment start (assuming code compiles at experiment start)
//otherwise toggle start/stop in the file menu
//if the functions attempt an auto save before a pxp has been saved (and thus has no name)
//then the name begins with ks_autoSaveBaseName followed by the year,month,day,hour,minute,second of the first save (underscore-delimited)

//constants that determine key aspects of auto save behavior -- user should adjust as preferred
static constant k_experimentAutoSaveRate_inMinutes = 30
static constant k_autoSaveCancelWindows_inSeconds = 20
static strconstant ks_autoSaveBaseName = "experimentAutoSave_"

//menu toggle
Menu "File", hideable,dynamic
    selectstring(getExperimentAutoSaveStatus(),"Toggle experiment auto save from off to ON","! Toggle experiment auto save from on to OFF"),/Q,experimentAutoSave("")
end

//start auto save on experiment start
function IgorStartOrNewHook(igorApplicationNameStr)
    String igorApplicationNameStr       //not used
   
    experimentAutoSave("on")    //this line should be added to IgorStartOrNewHook() if another exists already
end

//functions for auto save
function experimentAutoSave(onOrOffStr)
    String onOrOffStr       //"" to toggle, "on" to start, "off" to stop (any other string also defaults to "off")
   
    if (strlen(onOrOffStr) < 1) //toggle for ""
        onOrOffStr = selectstring(getExperimentAutoSaveStatus(),"on","off")
    endif
   
    strswitch (onOrOffStr)
        case "on":
            //one issue: when Ctrlnamedbackground runs, except apparently at start up, it attempts to auto save immediately when I think due to start=periodTicks it should wait until a full period has passed...
            Variable periodTicks = k_experimentAutoSaveRate_inMinutes*60*60     //convert to ticks (60 per second)
            Ctrlnamedbackground pxpSaveMainBgTask,dialogsOK=0,period=periodTicks,start=periodTicks,proc=pxpSaveMainBg       //set it to start after one period and not to run during dialogs
            print "experiment auto saves started at a rate of every",k_experimentAutoSaveRate_inMinutes,"minutes (adjust with k_experimentAutoSaveRate_inMinutes)"
            break
        default:
            killwindow/z pxpSavePanel
            ctrlnamedbackground pxpSaveHelperBgTask,kill=1  //kill the helper background task (which might or might not exist at a given run time)
            Ctrlnamedbackground pxpSaveMainBgTask,kill=1        //kill the main background task
    endswitch
end

//returns 1 if auto save is on, 0 if off
function getExperimentAutoSaveStatus()
    Ctrlnamedbackground pxpSaveMainBgTask,status  //if the main background task is running, auto save is ON
    return str2num(stringbykey("RUN",S_info))       //run is 1 if running, in which case auto save is also running
end

function pxpSaveMainBg(s)
    STRUCT WMBackgroundStruct &s
    //check if the experiment has been modified since last save and therefore needs saving
    experimentmodified
    if (!V_flag)
        return 0    //dont try to save at present but continue the background task
    endif
   
    //if there's already an auto save panel up, somehow an auto save is already scheduled to occur (might happen if k_experimentAutoSaveRate_inMinutes is really short relative to k_autoSaveCancelWindows_inSeconds
    if (wintype("pxpSavePanel") != 0)  
        return 0        //dont try to save at present but continue the background task
    endif
   
    newpanel/n=pxpSavePanel/w=(0,0,200,50)/k=1 as "Auto save experiment"   
    setwindow pxpSavePanel userdata(cancelCountdown)=num2str(k_autoSaveCancelWindows_inSeconds)
    Button cancelAutoSavePxp win=pxpSavePanel,fsize=15,fstyle=1,pos={20,2.5},size={170,40},title="CANCEL pxp auto save",proc=cancelAutoSavePxpBtn
    Ctrlnamedbackground pxpSaveHelperBgTask,period=60,start=60,dialogsOK=0,proc=pxpSaveHelperBg //start helper function running every 60 ticks (~1 second) and starting after 60 ticks
   
    return 0        //continue the background task
end

function pxpSaveHelperBg(s)
    STRUCT WMBackgroundStruct &s
   
    //cancel if the window has been killed and cancel if so
    if (wintype("pxpSavePanel") == 0)  
        return 1        //end this helper background function
    endif
   
    //check if the count down is over
    variable cancelCountdown = str2num(getuserdata("pxpSavePanel","","cancelCountdown"))
    if (cancelCountdown > 0)
        Button cancelAutoSavePxp win=pxpSavePanel,title=("CANCEL pxp auto save\rstarting in ~"+num2str(cancelCountdown)+" secs")
        setwindow pxpSavePanel userdata(cancelCountdown)=num2str(cancelCountdown-1)     //iterate down the timer
        return 0        //continue count down
    endif
   
    //figure out if the experiment has been saved before
    String pxpName = igorinfo(1)
    int hasPxpName = cmpstr(pxpName,"Untitled",1) != 0      //Note: experiments actually saved as "Untitled.pxp" appear to be an issue
    if (hasPxpName)     //been saved before, so easy to just resave
        saveexperiment
    else            //name is "Untitled", indicating that pxp has not been saved (or at his been saved as "Untitled", which would be problematic at present!)
        int secs = datetime
        String timeStr = replacestring("-",secs2date(secs,-2),"_") +"_"+replacestring(":",secs2time(secs,3),"_")
        String savename = ks_autoSaveBaseName + timeStr + ".pxp"
        pathinfo IgorUserFiles
        print "experimentAutoSave() this pxp appears to be previously unsaved. Pxp will be saved with the automatically generated name:",savename,"in folder="+S_path
        saveexperiment/p=IgorUserFiles as savename
    endif
   
    killwindow pxpSavePanel     //kill the panel
    experimentmodified 0            //since we just killed the window, the experiment has been modified, but it's not a reason to save again next round, so mark experiment unmodified
   
    return 1        //end this helper background function
end

function cancelAutoSavePxpBtn(s) : ButtonControl
    STRUCT WMButtonAction &s
   
    if (s.eventcode != 2)       //only react to mouse up in button area
        return 0
    endif
   
    Ctrlnamedbackground pxpSaveHelperBgTask,kill=1
    killwindow pxpSavePanel
end

//end of functions for auto save

 

One issue with these auto save approaches is that a save can take a long time for a large file, which will disrupt whatever the instance of Igor is doing. Adobe Illustrator auto-saves in a parallel task, so you can keep working. I think it would be really nice if Igor did that.

I'm not sure it's something that could be programmed by users -- I think it would have to be possible to initiate saving a copy of a pxp file from a parallel thread (and I'm not sure what happens if you try that). Once the copy is saved, the original pxp could optionally be overwritten by the copy. 

It also doesn't seem straightforward for a user/programmer to auto save stand-alone files (Notebooks, procedures). For example, I don't see a documented way to tell whether a notebook is adopted or saved into a stand-alone file (and thus in potential need of autosaving).

Hi,

One strategy I have used in the past for metrology tool I built is to use an unpacked experiment where the waves are saved to a folder. That way if the system crashed the data files would still be there. Additionally the operating system did a back up to save the data.

Andy

In reply to by hegedus

hegedus wrote:
One strategy I have used in the past for metrology tool I built is to use an unpacked experiment where the waves are saved to a folder. That way if the system crashed the data files would still be there.

I haven't used unpacked experiment files much, but wouldn't you still have to save the unpacked experiment (or the individual waves, as ibws) in order to avoid losing changes that you've made to the data in Igor? If you've been working on an unpacked experiment and the computer crashes, you're going to lose the changes just as for a packed experiment (please correct me if I am wrong).

You are correct about the save and if i recall (this was ~10 years back and I don't have access to the code any longer) that I saved the new data waves when they there generated so it was not the whole experiment.  Also The procedure and history are saved in easily readable text files.

Andy

Igor 9 (soon in beta) has autosave built in. There are options for saving an entire experiment vs. standalone files only, and options to save to the original files vs. saving to a ".autosave" file instead. Even then, if the user-configurable autosave interval has not expired since the last save, any changes made since the last save will be lost.

If you are primarily acquiring data, I recommend that you save the data as soon as you acquire it (or as soon as practical) so that Igor crashing or a power failure won't cause you to lose data. I like to write data to an HDF5 file, since this is a binary format that can be easily appended to, so you don't need to rewrite the entire file each time you save like you would with a packed experiment.

Sounds great. Is there any chance that saving (and autosaving) could occur in the background, so that Igor can keep running during the save?

In reply to by gsb

gsb wrote:

Sounds great. Is there any chance that saving (and autosaving) could occur in the background, so that Igor can keep running during the save?

No, I believe the autosave will only do the save if nothing else is happening (eg. no procedures running, etc.). The save code all runs from the main thread, so it needs to be run only when Igor is idle. This means that if you enable autosaving experiments, and saving your experiment takes more than a trivial amount of time, you'll probably notice a bit of lag when autosave kicks in. But if you are only autosaving procedure files, I don't expect you'll notice much lag unless the files are located on a network share and the save is relatively slow.