#pragma rtGlobals=1 // Use modern global access method. // ABOUT MULTI-EXPERIMENT PROCESS // This procedure file demonstrates a process that runs across multiple experiments. // The challenge was to open a series of packed experiment files (with ".pxp" extensions) in a particular folder. // Each experiment file contained waves named wave_lif1 and wave_lif2. We were asked to graph these waves // and then export the graph as a PNG file and then to repeat the process for the next experiment. // This file contains the procedures that cycle through experiments and execute a function for each experiment. // When a file is opened, Igor calls the AfterFileOpenHook hook in this file. The hook checks to see if // the file being opened is a packed experiment file and if it contains the expected waves. If so, // the hook function calls a subroutine that graphs the waves and exports the graph as a PNG file. // It then opens the next experiment file and repeats the process. // This procedure file uses Igor's LoadPackagePreferences and SavePackagePreferences to store // information used between invocations of AfterFileOpenHook. It uses Execute/P to post commands // to Igor's operation queue for opening the next experiment. // TO TRY THE DEMO // Choose File->Example Experiments->Programming->Multi-Experiment Process to open // the demo experiment and follow the instructions therein. //KJZ //To use this, you need a text wave called Experiment_Paths_Wave that contains the FULL paths to the experiments you want to run. The code assumes //that this is an Igor text file. You will also need the full path to this file. //In the function StartMultiExperimentProcess (or search for GRAPE), change the path to the experiment list file. //In the function ProcessCurrentExperiment (or search for KIWI), edit the list of commands to perform. If you use any external functions, //the ipf containing the function (or a shortcut to that ipf) needs to be in the Igor procedures folder!!! //Set kvIndex_Increment to the number of Igor instances you have open. //A shortcut/alias to this ipf needs to be in your Igor Procedures folder. //When you start the multiexperiment process by calling StartMultiExperimentProcess, you will need to supply the starting index for that instance of Igor. Menu "Macros" "Start Multi-Experiment Process", /Q, StartMultiExperimentProcess() End // NOTE: If you use these procedures for your own purposes, change the package name // to a distinctive name so that you don't clash with other people's preferences. static StrConstant kPackageName = "RunDOASISAnalysis" static StrConstant kPreferencesFileName = "RunDOASISAnalysisPrefs.bin" static Constant kPrefsRecordID = 0 // The recordID is a unique number identifying a record within the preference file. STATIC CONSTANT kvIndex_Increment=3 //Number of instances of Igor you have open // The structure stored in preferences to keep track of what experiment to load next. // If you add, remove or change fields you must delete your old prefs file. See the help // topic "Saving Package Preferences" for details. Structure MultiExperimentProcessPrefs uint32 version // Prefs version uint32 processRunning // Truth that we are running the mult-experiment process char folderPath[256] // Path to folder containing experiments. This can't be a string due to restrictions with LoadPackagePreferences (see the help for that function) uint32 index // Zero-based index of next experiment in folder to load uint32 experimentsProcessed uint32 experimentsSkipped EndStructure // In version 101 of the prefs structure we increased folderPath from 100 to 256 bytes static Constant kPrefsVersionNumber = 101 // Loads preferences into our structure. static Function LoadPackagePrefs(prefs) STRUCT MultiExperimentProcessPrefs &prefs Variable currentPrefsVersion = kPrefsVersionNumber // This loads preferences from disk if they exist on disk. LoadPackagePreferences /MIS=1 kPackageName, kPreferencesFileName, kPrefsRecordID, prefs // Printf "%d byte loaded\r", V_bytesRead // If error or prefs not found or not valid, initialize them. if (V_flag!=0 || V_bytesRead==0 || prefs.version!=currentPrefsVersion) prefs.version = currentPrefsVersion prefs.processRunning = 0 prefs.folderPath = "" prefs.index = 0 prefs.experimentsProcessed = 0 prefs.experimentsSkipped = 0 SavePackagePrefs(prefs) // Create default prefs file. endif End // Saves our structure to preferences. static Function SavePackagePrefs(prefs) STRUCT MultiExperimentProcessPrefs &prefs SavePackagePreferences kPackageName, kPreferencesFileName, kPrefsRecordID, prefs End // This is the routine that you would need to change to use this procedure file for your own purposes. // See comments about labeled "TO USE FOR YOUR OWN PURPOSES". static Function ProcessCurrentExperiment(prefs) STRUCT MultiExperimentProcessPrefs &prefs //KIWI //Example code. Usually this is a function call to another ipf Sleep/S 5 PathInfo home String strPath=S_Path String strDate_Time=ReplaceString("-", Secs2Date(DateTime, -2), "")+"_"+ReplaceString(":", Secs2Time(DateTime, 3), "") String strPXP_Name=IgorInfo(1) String strFile_Name=strPXP_Name+"_"+strDate_Time+".png" SavePICT/O/E=-5/C=0/B=288 as strPath+strFile_Name Sleep/S 5 //End of example code //Make sure to have this so your work gets saved! SaveExperiment End static Function IsAppropriateExperiment() // IF(WaveExists(wWavelength_nm_Ch1) || WaveExists(wWavelength_nm_Ch1)) return 1 // This looks like the kind of function we want to process. // ELSE // return 0 // This does not appear to be the kind of experiment we want to process. // ENDIF END // Returns full path to the next experiment file to be loaded or "" if we are finished. static Function/S FindNextExperiment(prefs) STRUCT MultiExperimentProcessPrefs &prefs String strPath2WaveList = prefs.folderPath DFREF dfrCurrentFolder=GetDataFolderDFR() //Gets the current data folder NewDataFolder/O/S root:Sparkly_Temp_Folder //Makes a new data folder to hold Experiment_Paths_Wave LoadWave/T/O/Q strPath2WaveList //Loads Experiment_Paths_Wave into Sparkly_Temp_Folder Wave/T/Z Experiment_Paths_Wave=root:Sparkly_Temp_Folder:Experiment_Paths_Wave IF(prefs.index>=numpnts(Experiment_Paths_Wave)) return "" ENDIF String strPXP_Path=Experiment_Paths_Wave[prefs.index] KillWaves/Z Experiment_Paths_Wave SetDataFolder dfrCurrentFolder KillDataFolder/Z root:Sparkly_Temp_Folder GetFileFolderInfo/Q/Z strPXP_Path IF(V_Flag!=0) Print "Path is invalid: "+strPXP_Path ENDIF return strPXP_Path End // Posts commands to Igor's operation queue to close the current experiment and open the next one. // Igor executes operation queue commands when it is idling - that is, when it is not running a // function or operation. static Function PostLoadNextExperiment(nextExperimentFullPath) String nextExperimentFullPath Execute/P "NEWEXPERIMENT " // Post command to close this experiment. // Post command to open next experiment. String cmd sprintf cmd "Execute/P \"LOADFILE %s\"", nextExperimentFullPath Execute cmd End // This is the hook function that Igor calls whenever a file is opened. We use it to // detect the opening of an experiment and to call our ProcessCurrentExperiment function. static Function AfterFileOpenHook(refNum,file,pathName,type,creator,kind) Variable refNum,kind String file,pathName,type,creator STRUCT MultiExperimentProcessPrefs prefs LoadPackagePrefs(prefs) // Load our prefs into our structure if (prefs.processRunning == 0) return 0 // Process not yet started. endif // Check file type // if (CmpStr(type,"IGsU") != 0) // return 0 // This is not a packed experiment file // endif // Check for expected waves if (IsAppropriateExperiment()) ProcessCurrentExperiment(prefs) prefs.index += kvIndex_Increment // Index tracks next experiment to be processed. prefs.experimentsProcessed += 1 else DoAlert 0, "This experiment is not suitable. Skipping to next experiment." prefs.experimentsSkipped += 1 endif // See if there are more experiments to process. String nextExperimentFullPath = FindNextExperiment(prefs) if (strlen(nextExperimentFullPath) == 0) // Process is finished prefs.processRunning = 0 // Flag process is finished. Execute/P "NEWEXPERIMENT " // Post command to close this experiment. String strDateTime=Secs2Date(DateTime, -2)+" "+Secs2Time(DateTime, 3) String message sprintf message, "Multi-experiment process is finished at "+strDateTime+". %d experiments processed, %d skipped.", prefs.experimentsProcessed, prefs.experimentsSkipped DoAlert 0, message else // Load the next experiment in the designated folder, if any. PostLoadNextExperiment(nextExperimentFullPath) // Post operation queue commands to load next experiment endif SavePackagePrefs(prefs) return 0 // Tell Igor to handle file in default fashion. End static Function PossiblySaveCurrentExperiment() DoIgorMenu/C "File", "Save Experiment" // Check if current experiment can be saved. if (V_flag == 0) // Experiment is not modified. return 0 endif DoAlert 2, "Save current experiment before starting?" if (V_flag == 1) // Yes SaveExperiment endif if (V_flag == 3) // Cancel return -1 endif return 0 End // Allow user to choose the folder containing the experiment files and start the process. Function StartMultiExperimentProcess([Variable vStart_Index]) STRUCT MultiExperimentProcessPrefs prefs // First save current experiment if necessary. if (PossiblySaveCurrentExperiment()) return -1 // User cancelled endif //GRAPE- Change this file path String strPath2WaveList="" GetFileFolderInfo/Q/Z strPath2WaveList IF(V_Flag!=0 || !V_IsFile) Abort "Path to experiment list is invalid!" ENDIF IF(ParamIsDefault(vStart_Index)) Prompt vStart_Index, "Enter starting index" DoPrompt "Enter values", vStart_Index IF(V_Flag) Return -1 ENDIF ENDIF LoadPackagePrefs(prefs) // This initializes prefs if they don't yet exist prefs.processRunning = 1 // Flag process is started. prefs.folderPath = strPath2WaveList // S_path is set by PathInfo prefs.index = vStart_Index prefs.experimentsProcessed = 0 prefs.experimentsSkipped = 0 // Start the process off by loading the first experiment. String nextExperimentFullPath = FindNextExperiment(prefs) PostLoadNextExperiment(nextExperimentFullPath) // Start the process off SavePackagePrefs(prefs) return 0 End