#pragma rtGlobals=1 // Use modern global access method. #pragma version = 1.3 //Third version; should still be compatible with Igor 5.0. Menu "jtgSpectroscopy" Submenu "Other Data Load Procs" "File Load",MultiFileLoad() End End //*****************************************************************************************************************// //***** Notes *****// //*****************************************************************************************************************// // 4/21/2008 // // --User can change the string constants below as well as the menu entry above as needed. // // The function bpMFLGetSelectedFileList will compile a string containing a semicolon // // separated list of files selected from the listbox. The user could operate on each selected // // item as it is found by adding code to bpMFLGetSelectedFileList or simply operate on // // the string after bpMFLGetSelectedFileList completes . The selected list is saved in a // // string named FileList in a folder that is in the path dictated by ksDFPath. The folder is // // uniquely named using a base name of MultiFileLoadPanel. // // 3/21/2010 // // --Added structure with file name list and path to disk files to make it easier to pass this // // on to a file loading function. // // --Modified popFuncList Popup Menu on the panel. This Popup Menu can be used to select a // // function to process the list of selected files. The function GetFileLoaderList is used to // // supply the menu item list. All functions in memory ending in "_MFL" will be included in the // // list. File processing functions must take as a single input a structure of the type // // structJTG_MFL. Otherwise the prototype function will be called. This function merely // // reports that there was a problem with the selected function. A numeric constant // // (kHideFunctionList) at the top of this procedure file controls whether the Popup Menu is // // enabled or not: If kHideFunctionList == 0, menu is shown; == 1 is hidden and for all other // // values, it will be shown but will be disabled. If the popup menu is not hidden, the selected // // function will be called once the list of selected files is compiled. // // --Because of the change to the behavior of popFuncList, the KnownFuncLists string variable // // has been removed from the function that creates the panel (MultiFileLoad()). // // 3/22/10 // // --Fixed start up behavior of the panel so that the list box is filled with files from the default // // disk folder in ksDefaultDataPath. If that path doesn't exist, Igor pops up a dialog to find it. // // --Along with this, it might be helpful to provide a means to limit the types of files listed. This // // could be achieved using the fileTypeOrExtStr parameter of the IndexedFile function. // // Currently, all files in the folder are listed, using the "????" form of fileTypeOrExtStr. // // For now this could be easily (but not transparently) done using a string constant. This has // // been implimented. See string constant ksFileTypeOrExtension below. The function // // GetFileList now uses this constant when producing the file list. // //*****************************************************************************************************************// //*****************************************************************************************************************// //***** Constants and Structures *****// //*****************************************************************************************************************// //Name of Igor datafolder path used for file load functions. Static StrConstant ksDFPath = "root:Packages:JTG:MultiFileLoader:" //Path to default disk folder that provides list of files. It is suggested that the path expression use the //Macintosh file system convention of employing a colon to separate elements in a file path. For example: //"C:MyStuff:pg:Fluorescence:Data:SPEX_Data:SPEX FL3-22 Data:Data Files:2007:" //The default path shown here points to the root directory on drive C. Static StrConstant ksDefaultDataPath = "C:" //Variable to control display of popFuncList (list of functions that can be used to process selected files): //0 == Normal, 1 == hide, 2 == show, but disable. Static Constant kHideFunctionList = 0 //Variable to control types of files appearing in file list box. Set to "????" for any file type or limit with //extension including the preceeding "." as in ".dat" for files with a "dat" extension. Static StrConstant ksFileTypeOrExtension = ".spc" Structure structJTG_MFL String sFileNameList //semicolon separated list of selected files String sPathToFiles //colon separated path to disk files EndStructure //*****************************************************************************************************************// //***** End of Constants and Structures *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** MultiFileLoad *****// //*****************************************************************************************************************// // --Start Multiple file load routine. Display control panel; create waves used to handle waves // // and wave selections. // // 10/31/06 // // --Modified code so that data folders are used to hold waves (list of files) and string // // unique to a MultiFileLoad panel. Now multiple panels can be open and each will retain // // its own unique information set; each of which can open files from different directories. // // A hook function is set for each open panel and when the panel is killed the associated // // data folder and waves are also killed. // // 4/21/08 // // --Removed file loading specific code and generalized so that a string list of selected // // files is compiled and stored in the panel specific data folder. // // 3/21/10 // // --Removed KnownFuncLists string variable and moved to GetFileLoaderList() function to // // set value list for popFuncList popup menu control. // // --The popup menu controlpopFuncList is enable/disabled by the value of the string constant // // kHideFunctionList (appears at beginning of the procedure file). This control shows a list of // // procedures from which user to choosea single entry for procesing the selected files. The // // popup menu's value list is filled by the function GetFileLoaderList(). // // 3/22/10 // // --When control panel is created, the symbolic path that points to the disk folder containing // // files to be acted on is set to the default value specified in ksDefaultDataPath. If the disk // // does not exist, the standard Igor dialog for finding the folder pops up. This can be prevented // // by adding the "/Z" flag to the NewPath operation near the end of this function. When the // // symbolic path is set, GetFileList is called to fill the list box with files located in the folder. // //*****************************************************************************************************************// Function MultiFileLoad() String PanelName String DFName String DataLocation PanelName = UniqueName("MultiFileLoadPanel", 9, 0 ) DataLocation = ksDFPath + PanelName //Create data folders to hold panel info; ksDFPath is string constant //see top of procedure file for its value. Folder has same name as panel name. CreateDFPath(ksDFPath, PanelName) String/G $(DataLocation + ":PathToFiles") = ksDefaultDataPath make /O /T /N=10 $(DataLocation + ":w") make /O /B /U /N=10 $(DataLocation + ":sw") = 0 Wave/T w = $(DataLocation + ":w") Wave sw = $(DataLocation + ":sw") String/G $(DataLocation + ":FileList") = "" String/G $(DataLocation + ":FileNumberList") = "" Variable/G $(DataLocation + ":NumberOfFiles") = 0 PauseUpdate; Silent 1 // building window... NewPanel /K=1 /W=(338.0,67.0,776,288) DoWindow /C $PanelName //change graph window name DoWindow /T $PanelName PanelName //change graph window title SetVariable svPath,pos={66,24},size={284,16},proc=GetFileList,title="Path" SetVariable svPath,value= $(DataLocation + ":PathToFiles") //PathToFiles Button btnSetPath,pos={8,22},size={50,20},proc=bpMFLSetPath,title="Set Path" Button btnUpdateList,pos={359,22},size={65,20},proc=bpMFLUpdateList,title="Update List" Button btnUpdateList,help={"Update list of files from current path."} GroupBox gbPath frame=1, title="Path", pos={2,5}, size={431, 43} ListBox lbFiles disable=0, editStyle= 0, listWave= w, mode=10, pos={2,55} ListBox lbFiles selWave=sw, size={200,150}, widths={200} Button btnGetSelectedFileList,pos={262,55},size={50,20},proc=bpMFLGetSelectedFileList,title="Get Files" PopupMenu popFuncList,disable=kHideFunctionList,pos={206,90},size={158,21},title="File Loader" PopupMenu popFuncList,mode=1,proc=poprocFuncList PopupMenu popFuncList, value=GetFileLoaderList() //list of known file types for pop up menu //set symbolic path to default disk path (ksDefaultDataPath) NewPath /O/Q jtgSpecFileLoader , ksDefaultDataPath GetFileList("",0,"","") //set window hook for this panel; hook function is MultiFileLoadHook SetWindow kwTopWin, hook(MultiFileLoadCleanUp )=MultiFileLoadHook End Function //*****************************************************************************************************************// //***** End of MultiFileLoad *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** MultiFileLoadHook *****// //*****************************************************************************************************************// // 10/31/06 // // --Added function. This is an event processing function for the control panel created by // // MultiFileLoad function. The first intended purpuose is to clean up when the MultiFileLoad // // panel is killed. It is used to delete waves ("w" & "sw") and folder created by when the panel // // is opened. // //*****************************************************************************************************************// Function MultiFileLoadHook(s) STRUCT WMWinHookStruct &s Variable statusCode = 0 String PanelName String DFName PanelName = s.winName DFName = ksDFPath + PanelName if(s.eventCode == 2) //kill window: clean up KillDataFolder $DFName statusCode = 1 endif return statusCode // 0 if nothing done, else 1 End //*****************************************************************************************************************// //***** End of MultiFileLoadHook *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** bpMFLSetPath *****// //*****************************************************************************************************************// // --Called by Set Path button on panel. Opens dialog to select new symbolic path to // // directory containing files to load. Then calls routine to get all files from that directory and // // load into wave w for display in the list box. // // 10/31/06 // // --Modified for data folder use. // //*****************************************************************************************************************// Function bpMFLSetPath(ctrlName) String ctrlName String Msg String PanelName String DataLocation if(stringmatch(ctrlName, "btnSetPath") != 1) return 0 endif //string and waves associated with this panel instance are located in a data folder named //after the panel name PanelName = WinName(0, 64) //name of top panel DataLocation = ksDFPath + PanelName SVAR PathToFiles = $(DataLocation + ":PathToFiles") Msg = "Browse To The File Location..." NewPath /M=Msg /O jtgSpecFileLoader if(V_flag != 0) //user hit cancel return 0 endif PathInfo jtgSpecFileLoader if(V_flag == 0) //path doesn't exist return 0 endif //update path variable; S_path is variable created by PathInfo operation PathToFiles = S_path //fill listbox with files from new path GetFileList("",0,"","") End Function //*****************************************************************************************************************// //***** End of bpMFLSetPath *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** poprocFuncList *****// //*****************************************************************************************************************// // Currently, this is not really used although it is called when the popup menu popFuncList is // // accessed. This could, perhaps be used to limit the items appearing in the list boxt. Or // // maybe some other control could be used for this purpose. // //*****************************************************************************************************************// Function poprocFuncList(ctrlName,popNum,popStr) : PopupMenuControl String ctrlName Variable popNum String popStr if(stringmatch(ctrlName, "popFuncList") != 1) return 0 endif //debugging aid // print popStr End Function //*****************************************************************************************************************// //***** End of poprocFuncList *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** GetFileLoaderList *****// //*****************************************************************************************************************// // 3/22/10 // --This function provides a list of functions that can process the list of selected files. The list of // // functions can be hard wired as a semicolon separated list in the string variable // // KnownFuncList (see example commented lines below). Alternatively, if there are functions // // in the current experiment having names ending with "_MFL", then the FunctionList function // // can be used to load them into the KnownFuncList string. // // The functions must take as their only input a structure of the structJTG_MFL type. The // // structure has two member types: the list of selected files and the path to the files. // // This function is called when the panel is first loaded and then whenever the popFuncList // // menu is clicked on. // //*****************************************************************************************************************// Function/S GetFileLoaderList() : PopupMenuControl String KnownFuncList // KnownFuncList = "_Auto_;Spex (.SPT);PE L-9 (.SP);Foss (.TXT);HP UVVis (.WAV);HySPEC (.TIF); TIFF (.TIF);" // KnownFuncList += "MM log (.LOG);GRAMS (.SPC);Text (.???);TextMatrix (.CSV)" KnownFuncList = FunctionList("*_MFL", ";", "KIND:2") if(strlen(KnownFuncList) == 0) //no functions found KnownFuncList = "" endif return KnownFuncList End Function //*****************************************************************************************************************// //***** End of GetFileLoaderList *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** bpMFLGetSelectedFileList *****// //*****************************************************************************************************************// // --Called by Get Files buttons on controll panel. Check wave sw to determine which files // // were selected and assign to output string. The selected list is saved in a string named // // FileList in a folder that is in the path dictated by ksDFPath. The folder is uniquely named // // using a base name of MultiFileLoadPanel. // // --User specific code could be put in the if/endif segment in this procedure or user could act // // on FileNameList stored in the package folder // // 10/31/06 // // --Modified for data folder use. // // 3/22/10 // // --Queries popFuncList control to determine which routine to call for loading the files. If there // // are no file handling functions, then the routine just exits. It is then up to the user to pass // // the file list on to another processing function. // //*****************************************************************************************************************// Function bpMFLGetSelectedFileList(ctrlName) String ctrlName Variable index Variable NumFiles String FPath_Name String FName String FuncName //name of function to call to proces file list String FBaseName String FExtension String PanelName String DataLocation if(stringmatch(ctrlName, "btnGetSelectedFileList") != 1) return 0 endif Struct structJTG_MFL strFileList //string and waves associated with this panel instance are located in a data folder named //after the panel name PanelName = WinName(0, 64) //name of top panel DataLocation = ksDFPath + PanelName Wave/T w = $(DataLocation + ":w") Wave sw = $(DataLocation + ":sw") SVAR PathToFiles = $(DataLocation + ":PathToFiles") SVAR FileNameList = $(DataLocation + ":FileList") NVAR NumberOfFiles = $(DataLocation + ":NumberOfFiles") SVAR FileNumberList = $(DataLocation + ":FileNumberList") FileNameList = "" FileNumberList = "" NumFiles = numpnts(sw) index = 0 //Step through each element in listbox selection wave (sw) to determine which, if any items were selected. //Compile a string variable with all selected entries. Do //bit one or bit 3 of sw is set if listbox row(index) was selected (listbox mode 10) //user specific code could be put in this if/endif segment //or user could act on FileNameList stored in the package folder if(((sw[index] & 0x01) || (sw[index] & 0x08)) == 1) FName = w[index] FileNameList += FName + ";" FileNumberList += num2str(index) + ";" FPath_Name = PathToFiles + FName FBaseName = ParseFilePath(3, FName, ":", 0, 0) FExtension = ParseFilePath(4, FName, ":", 0, 0) endif index += 1 While (index < NumFiles) NumberOfFiles = ItemsInList(FileNameList, ";") //Write list of selected items and disk path to structure variables. strFileList.sFileNameList = FileNameList strFileList.sPathToFiles = PathToFiles //Check status of popFuncList //Call Get_popFuncListInfo to get name of selected item in popFuncList. If there is a problem with //the control status or if it is hidden, Get_popFuncListInfo will return a null string. In this case, do //not attempt to call the list processing function. Thus this behavior, calling a function through this //interface can be disabled by hiding the popup menu control. Otherwise pass the data structure //and function name to the function that will call the file processing function. FuncName = Get_popFuncListInfo("popFuncList") if(strlen(FuncName) != 0) //FuncName is not null CallFileLoader(strFileList, FuncName) endif //At this point the user could place a function call to a file processing function. That function could //either use the structure strFileList or the individual strings (FileNameList and PathToFiles) to process //the files. That function call could be place here, for example. //For debugging print a list of files selected for loading and a list of their position in the //wave of all files in directory. // print FileNameList // print FileNumberList End Function //*****************************************************************************************************************// //***** End of bpMFLGetSelectedFileList *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** GetFileList *****// //*****************************************************************************************************************// // --Get list of files from current path jtgSpecFileLoader, redimension waves used to hold // // file names and list box attributes. // // --This will automatically put new list into listbox. // // 10/31/06 // // --Modified for data folder use. // // 6/20/07 // // --Added line "sw = 0" to clear all selections when the listbox is updated. // // 3/22/10 // // --Added a means to limit the types of files listed using the fileTypeOrExtStr parameter of the // // IndexedFile function and the string constant ksFileTypeOrExtension (defined at head of the // // procedure file. If ksFileTypeOrExtension = "????", all files in the folder are listed. If, instead, // // ksFileTypeOrExtension is set to "." + file extension (ie, ".dat") only files with the given // // extension will be listed. // //*****************************************************************************************************************// Function GetFileList(ctrlName,varNum,varStr,varName) String ctrlName Variable varNum // value of variable as number String varStr // value of variable as string String varName // name of variable String PanelName String DataLocation //String and waves associated with this panel instance are located in a data folder named //after the panel name. PanelName = WinName(0, 64) //name of top panel DataLocation = ksDFPath + PanelName Wave/T w = $(DataLocation + ":w") Wave sw = $(DataLocation + ":sw") Variable NumFiles //Get list of files in the folder pointed to by the symbolic path jtgSpecFileLoader; this list is limited by file type or //extension stored in string constant ksFileTypeOrExtension. Formerly, this was hardwired to list all files, as shown //in the line commented out immediately below. If no files are found matching the specification, //IndexedFile returns and empty string "". // String FileList = IndexedFile(jtgSpecFileLoader, -1, "????") String FileList = IndexedFile(jtgSpecFileLoader, -1, ksFileTypeOrExtension) //Sort list of files before storing in file name wave w FileList = SortList(FileList, ";", 16) //16: case-insensitive alphanumeric sort that sorts wave0 and wave9 before wave10. NumFiles = itemsinlist(FileList, ";") //Redimension waves used for file list and selection of files in list to match number of entries in FileList. Redimension /N=(NumFiles) w Redimension /N=(NumFiles) sw sw = 0 //clear all previous selections w[] = StringFromList(p, FileList, ";") //store list of file names in w End Function //*****************************************************************************************************************// //***** End of GetFileList *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** CallFileLoader *****// //*****************************************************************************************************************// // 3/21/10 // // --Function to call the function to handle the list of selected files. // // --Function prototype (FileLoader_Prototype) appears at the end of this procedure. There are // // also two example file handling functions following the prototype. // // --If the function passed to CallFileLoader does not match the prototype specification, the // // prototype will be called. The prototype function only displays a message in the history // // window indicating that the passed function was problematic. // //*****************************************************************************************************************// Function CallFileLoader(s, funct) Struct structJTG_MFL &s String funct FUNCREF FileLoader_Prototype f = $funct f(s) End //*****************************************************************************************************************// //***** End of CallFileLoader *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** bpMFLUpdateList *****// //*****************************************************************************************************************// // --Update list of files in displayed in list box lbFiles. // // --This button procedures just calls GetFileList procedure. // // 01/17/07 // // --Modified for data folder use. // //*****************************************************************************************************************// Function bpMFLUpdateList(ctrlName) String ctrlName if(stringmatch(ctrlName, "btnUpdateList") != 1) return 0 endif GetFileList("",0,"","") End Function //*****************************************************************************************************************// //***** End of bpMFLUpdateList *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** Get_popFuncListInfo *****// //*****************************************************************************************************************// // 03/22/2010 // // --Added function to check the status of popFuncList. Returns null string if the popup menu is // // hidden, is of the wrong control type or does not exist. If everything is ok, then the name of // // the selected function is returned. // //*****************************************************************************************************************// Function/S Get_popFuncListInfo(ctrlName) String ctrlName String sRtn = "" ControlInfo $ctrlName //if the control recreation macro is null, the control doesn't exist. Return null string. if(strlen(S_recreation) == 0) sRtn = "" print ctrlName, " Control does not exist on the current contol panel." return sRtn endif //hidden, don't call file loader if(V_disable == 1) sRtn = "" print ctrlName, " Control is hidden." return sRtn endif //control is not a popup menu type if(abs(V_flag) != 3) sRtn = "" print ctrlName, " Control is not a popup menu." return sRtn endif //control value is null; strlen returns "NAN" if(numtype(strlen(S_Value)) != 0) sRtn = "" print ctrlName, " Control value is null." return sRtn endif //everything is ok, return popup menu selection //this is the name of the function to process the list of selected files return S_Value End Function //*****************************************************************************************************************// //***** End of Get_popFuncListInfo *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** Static Function CreateDFPath *****// //*****************************************************************************************************************// // --Standard function used to created a new data folder and the path to it if it does not exist. // // Function is declared as static in case it exists in other open procedure files. // //*****************************************************************************************************************// Static Function CreateDFPath(sFullDFPath, sNewDF) String sFullDFPath String sNewDF String sEntireDFPath //path plus new folder Variable incr String sPathElement = "" String sPartialPath = "" String sPathChar = "" sEntireDFPath = sFullDFPath + sNewDF //check that path and folder strings aren't empty if((strlen(sFullDFPath) == 0) || (strlen(sNewDF) == 0 ) == 1) DoAlert 0, "Missing Data Folder Path... check string constant at start of procedure." return 0 endif //Does path already exist? //then check for its existence, if it alrealdy exists, alert user and return success If(DataFolderExists(sEntireDFPath)) //print "Path already exists: ", sEntireDFPath return 1 EndIf //Are there any ":" at front? Do sPathChar = sEntireDFPath[0] if(stringmatch(sPathChar, ":") == 0) break endif sPartialPath += ":" sEntireDFPath = sEntireDFPath[1, inf] While(1) incr = 0 //if the first part of the path is "root:", this is a special case. It always exists and we don't //need to create it, so skip over it. //break path at folders and work with each part of the path sPathElement = StringFromList(incr, sEntireDFPath, ":") If(stringmatch(sPathElement, "root")) sPartialPath = "root:" incr += 1 EndIf Do //break path at folders and work with each part of the path sPathElement = StringFromList(incr, sEntireDFPath, ":") //exit loop when we encounter a null string, this usually means that all elements of loop //have been processed If(!strlen(sPathElement)) break EndIf sPartialPath += sPathElement // print "creating: ", sPartialPath NewDataFolder/O $sPartialPath //need ":" to separate path elements, but NewDataFolder doesn't like this on the end of a path //string, so we append it here. sPartialPath += ":" incr += 1 While(1) return 1 End //*****************************************************************************************************************// //***** End of CreateDFPath *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** FileLoader_Prototype *****// //*****************************************************************************************************************// // 3/21/10 // // --Prototype file handling function for FUNCREF in CallFileLoader function. // // --The only criteria for a file handling function is that it take a single input parameter of // // Structure structJTG_MFL type. // // If a file handling function is to be included in the PopupMenu popFuncList, its name must // // end in "_MFL". // // --Two very simple example file handling functions follow this function. // //*****************************************************************************************************************// Function FileLoader_Prototype(s) Struct structJTG_MFL &s print "proto function, if you are reading this there is a problem with the FuncRef" //example file processing function //do something End //*****************************************************************************************************************// //***** End of FileLoader_Prototype *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** FileLoader_Test1_MFL *****// //*****************************************************************************************************************// // 3/21/10 // // --Example file handling function #1. Note that its name end's with "_MFL" and takes one // // input parameter of Structure structJTG_MFL type. // // --Uncomment the function to have it appear in PopupMenu popFuncList // //*****************************************************************************************************************// Function FileLoader_Test1_MFL(s) Struct structJTG_MFL &s print "FileLoader_Test1_MFL" print s.sFileNameList print s.sPathToFiles End //*****************************************************************************************************************// //***** End of FileLoader_Test1_MFL *****// //*****************************************************************************************************************// //*****************************************************************************************************************// //***** FileLoader_Test2_MFL *****// //*****************************************************************************************************************// // 3/21/10 // // --Example file handling function #2. Note that its name end's with "_MFL" and takes one // // input parameter of Structure structJTG_MFL type. // // --Uncomment the function to have it appear in PopupMenu popFuncList // //*****************************************************************************************************************// Function FileLoader_Test2_MFL(s) Struct structJTG_MFL &s print "FileLoader_Test2_MFL" print s End //*****************************************************************************************************************// //***** End of FileLoader_Test2_MFL *****// //*****************************************************************************************************************//