SetDataFolder string input

If a function does work in a data folder, I try to restore the original folder when the function is done using a combination of GetDataFolder and SetDataFolder.  When resetting the data folder, I forgot to put the $ before the string, and somehow it still worked.  The help for SetDataFolder says the input is "dataFolderSpec," which, based off the examples in the help, I always assumed meant either the name of the folder or a data folder reference, and that If I wanted to use a string with the name of the folder, I would have to preface the string with a $.  Instead, in this case, Igor seems to automatically use the value of the string.  What is also weird is that if there is a folder with the same name as the string, Igor will set the current data folder to value of the string, not the name, as shown in the function Weird().  Is SetDataFolder coded to always use the value of the string, regardless of whether there is a $ in front of the string?  I'm still on 8.04.2.  

//Final folder is root:Test_Folder, even though root:strCurrent_Data_Folder is a folder
FUNCTION Weird()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = GetDataFolder(1)       //Should be "root:Test_Folder"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
       
    Print DataFolderExists("root:strCurrent_Data_Folder")
   
    SetDataFolder strCurrent_Data_Folder
//  SetDataFolder root:strCurrent_Data_Folder       //This line won't compile

END

//Final folder is root:Test_Folder
FUNCTION Expected()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = GetDataFolder(1)       //Should be "root:Test_Folder"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
       
    SetDataFolder $strCurrent_Data_Folder

END

//Final folder is root:Test_Folder
FUNCTION Expected_2()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = GetDataFolder(1)       //Should be "root:Test_Folder"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
   
    SetDataFolder Test_Folder

END

//Final folder is root:strCurrent_Data_Folder
FUNCTION Expected_3()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = GetDataFolder(1)       //Should be "root:Test_Folder"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
   
    Print DataFolderExists("root:strCurrent_Data_Folder")
   
    SetDataFolder $"root:strCurrent_Data_Folder"

END

//This throws an error
FUNCTION Expected_4()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = "Hi_There"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
   
    Print DataFolderExists("root:strCurrent_Data_Folder")
   
    SetDataFolder strCurrent_Data_Folder

END

 

I don't think SetDataFolder does anything exceptionally magic.

The variable name strCurrent_Data_Folder makes the code a bit unwieldy to reason about, but I'll have a try.

The following is an adapted code example:

 

FUNCTION Weird()

    NewDataFolder/O/S root:Test_Folder
    string  strCurrent_Data_Folder = GetDataFolder(1)       //Should be "root:Test_Folder"
    Print strCurrent_Data_Folder
   
    NewDataFolder/O/S root:strCurrent_Data_Folder
   
    SetDataFolder root:
    print GetDataFolder(1)
   
    SetDataFolder $strCurrent_Data_Folder
    print GetDataFolder(1)

    SetDataFolder root:$"strCurrent_Data_Folder"
    print GetDataFolder(1)
END

which gives
 

•weird()
  root:Test_Folder:
  root:
  root:Test_Folder:
  root:strCurrent_Data_Folder:

1.) The first line from Print strCurrent_Data_Folder prints the *contents* of the string strCurrent_Data_Folder.

2.) The second line prints the CDF (current datafolder) after setting it to root:. Not very suprisingly this is root:.

3.) This sets the CDF to the path stored *inside* strCurrent_Data_Folder which is root:Test_Folder:.

4.) This sets the CDF to root:strCurrent_Data_Folder, Using $"XXX" is the same as XXX.

SetDataFolder expects a literal relative/absolute datafolder specification ("root:Test_Folder") or a datafolder reference (which we ignore here). This datafolder specification can be built up from literal strings "root:Test_Folder or from string variables $strCurrent_Data_Folder but in the last case you have to use $ to tell igor that it should look into the string variable and create a literal string from it.

So to rewrite your example as in

FUNCTION Various_Combiations()

    NewDataFolder/O/S root:Test_Folder
    string path = GetDataFolder(1)
   
    SetDataFolder root:

     // literal absolute path
    SetDataFolder root:Test_Folder
    print GetDataFolder(1)

    SetDataFolder root:

     // literal relative path
    SetDataFolder Test_Folder
    print GetDataFolder(1)

    SetDataFolder root:

     // using an absolute path which is build up from components
     string A = "Test"
     string B = "Folder"
    SetDataFolder root:$(A + "_" + B)
    print GetDataFolder(1)

    SetDataFolder root:
   
    // absolute path from inside the string variable
    SetDataFolder $path
    print GetDataFolder(1)
   
    // going crazy
    SetDataFolder $("ro" + "ot:" + A + "_" + B)
    print GetDataFolder(1)
END

this always sets the CDF to root:Test_Folder:.

Does that make sense?

I should have explained things better in my earlier post.  If you give SetDataFolder a string, I would expect different results depending on whether the string name is preceded by a $.  This is what happens when you use a string with NewDataFolder.  If the string is preceded by a $, then a folder gets created using the value of the string, and if there is not a $ then the new folder has the name of the string.  However, SetDataFolder seems to have some extra smarts, and if you pass a string it will always use the value of the string, regardless of whether or not there is a $.  

FUNCTION Data_Folders()

    SetDataFolder root:

    String Folder_Name="Data_Folder"
   
    NewDataFolder/O Folder_Name
    NewDataFolder/O $Folder_Name
   
    Print GetIndexedObjNameDFR(root:, 4, 0)     //Prints "Folder_Name"
    Print GetIndexedObjNameDFR(root:, 4, 1)     //Prints "Data_Folder"
   
    SetDataFolder Folder_Name
    Print GetDataFolder(1)              //Prints "root:Data_Folder:"
   
    SetDataFolder root:
   
    SetDataFolder $Folder_Name
    Print GetDataFolder(1)              //Also prints "root:Data_Folder:"
   
    SetDataFolder root:
   
END

To be clear, I have not had issues with this behavior, and I do appreciate that SetDataFolder has some user-proofing.  However, according to the help files the input for either command is simply "dataFolderSpec," so it was surprising that they behaved in a different fashion. Changing the behavior of either command seems like a bad idea at this point, and my newer code uses a data folder reference from GetDataFolderDFR instead of a string.  However, I just want to make sure I understand why the behavior is different for these functions.

As an aside, these days to save/restore the data folder, we recommend using GetDataFolderDFR() and SetDataFolder using the data folder reference. Like this:

Function setsDF()
    DFREF savedDF = GetDataFolderDFR()
        // do some work that changes the data folder
    SetDataFolder savedDF
end

But really, if you don't need to change the data folder, don't. You can always use a full data folder path to waves and global variables.

Now I'm getting your point :) Yes indeed SetDataFolder when passed a string variable always looks into it instead of taking it literally and that differs from what NewDataFolder does. I don't know why it is like that.