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.
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:
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
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
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?
October 18, 2022 at 02:27 pm - Permalink
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 $.
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.
October 18, 2022 at 04:57 pm - Permalink
As an aside, these days to save/restore the data folder, we recommend using GetDataFolderDFR() and SetDataFolder using the data folder reference. Like this:
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.
October 18, 2022 at 05:00 pm - Permalink
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.
October 19, 2022 at 12:07 am - Permalink
Yep- one of the mysteries enshrined in some moderately old code!
October 19, 2022 at 09:46 am - Permalink