cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
CitizenNo3
Level II

Saving a new script to preserve variables for later

Hello, 

I've built a script that performs data analysis but requires various user inputs to configure. There are cases where I want to perform a similar analysis later, but not need to re-enter all my settings. The main script already can read existing variables and auto-fill those fields, so if I have some way to save and import those default values, I'll be set. I want to be able to have multiple different configurations and not need to edit the script itself to make a new one. 

One idea was to save a table with a column of variable names and a column of their values, but that didn't play well with different variable types (numbers, strings, lists). 

A better-seeming idea is to save other .jsl files that contain the default settings for different use cases into a shared namespace, then run the relevant one before running my main script. I'd like to be able to create the configuration file from within my script, rather than manually making them. 

I found this other post about saving new jsl files. https://community.jmp.com/t5/Discussions/how-do-you-create-a-new-script-file-from-jsl/td-p/34740

It seems like I should be able to set up a JSL quote, then substitute the current values of variables into that quote, but NameExpr isn't working for that. Strings are substituted without quote marks, lists just appear as List and numbers are ignored. Is there a slight change that would make this work, or a better way to accomplish the same goal? 

Thanks!

names default to here (1);

//namespace for the shared variables
If( !Namespace Exists( "TestNS" ), New Namespace( "TestNS" ) );

//the variables I want to save for later
TestNS:a = 5;
TestNS:b = "text";
TestNS:c = {1,2,3,4};
TestNS:d = {"a","b","c","d"};

//set up script to save as JSL
script = JSL Quote( 	
	TestNS:a = a_dv;
	TestNS:b = b_dv;
	TestNS:c = c_dv;
	TestNS:d = d_dv;
);

//substitute the dummy values for the current values... this isn't working
substitute Into (script, expr(a_dv), nameexpr (TestNS:a));
substitute Into (script, expr(b_dv), nameexpr (TestNS:b));
substitute Into (script, expr(c_dv), nameexpr (TestNS:c));
substitute Into (script, expr(d_dv), nameexpr (TestNS:d));

show(script);

//save script for later use
Save Text File( "$downloads\MyScript.jsl", script );
3 ACCEPTED SOLUTIONS

Accepted Solutions
txnelson
Super User

Re: Saving a new script to preserve variables for later

I am not sure how universal this is, but it does work on your simple script

names default to here (1);

//namespace for the shared variables
If( !Namespace Exists( "TestNS" ), New Namespace( "TestNS" ) );

//the variables I want to save for later
TestNS:a = 5;
TestNS:b = "text";
TestNS:c = {1,2,3,4};
TestNS:d = {"a","b","c","d"};

//set up script to save as JSL
script = expr( 	
	TestNS:a = a_dv;
	TestNS:b = b_dv;
	TestNS:c = c_dv;
	TestNS:d = d_dv;
);

//substitute the dummy values for the current values... this isn't working
substitute Into (script, expr(a_dv), nameexpr (TestNS:a));
substitute Into (script, expr(b_dv), nameexpr (TestNS:b));
substitute Into (script, expr(c_dv), nameexpr (TestNS:c));
substitute Into (script, expr(d_dv), nameexpr (TestNS:d));

// Move the arguments in the script to a character string
theScript = "";
i=1;
While( char(arg(script,i)) !="Empty()",
	theScript = theScript || char(arg(script,i)) || ";";
	i++;
);

show(script);

//save script for later use
Save Text File( "$downloads\MyScript.jsl", theScript );
Jim

View solution in original post

jthi
Super User

Re: Saving a new script to preserve variables for later

Have you maybe consider storing those values into a associative array? It is most likely easier to manage and it can be saved for example as a JSON if needed.

 

Names Default To Here(1);

//namespace for the shared variables
If(!Namespace Exists("TestNS"),
	New Namespace(
		"TestNS"
	)
);

//the variables I want to save for later
TestNS:settings = Associative Array();
TestNS:settings["a"] = 5;
TestNS:settings["b"] = "text";
TestNS:settings["c"] = [1 2 3 4];
TestNS:settings["d"] = {"a", "b", "c", "d"};
TestNS:settings["e"] = ["key" => 1];


/*
TestNS:settings["a"] = cur_settings["a"];
TestNS:settings["b"] = cur_settings["b"];
TestNS:settings["c"] = cur_settings["c"];
TestNS:settings["d"] = cur_settings["d"];
TestNS:settings["e"] = cur_settings["e"];
*/

myfilepath = Save Text File("$DOWNLOADS/myscript.jsl", As JSON Expr(TestNS:settings));

conf = Load Text File(myfilepath);
loaded_settings = Parse JSON(conf);

You could then create few functions such as save_settings, load_settings, ... if needed.

-Jarmo

View solution in original post

CitizenNo3
Level II

Re: Saving a new script to preserve variables for later

Thanks to both Jarmo and Jim, both those solutions work. I initially used Jim's solution, which was able to plug directly into what I initially had. After some revision, I adapted Jarmo's idea which indeed was tidier to manage. Here is what I ended up with. With this setup I didn't need the namespace, but it would still work with namespaces.

 

names default to here (1);

//initialize variables
var1 = {"a", "b", "c"};
var2 = 100;
var3 = [1, 2, 3, 4];

//initialize variables used for functions
VarsToExport = {"var1", "var2", "var3"};
SettingsAA = Associative Array();
loaded_settingsAA = .;
SelfPath = Get Default Directory();

//expr to get each variable in the VarsToExport list and input the value into an AA, export as JSON
ExportVarsExpr = expr(
	for each({varname}, VarsToExport,
		//show(varname);
		SettingsAA[varname] = eval(as name(varname));
		//show(SettingsAA);
	);
	
	VarsSavePath = Pick File(
		"Save a file containing current script settings",
		SelfPath,
		{"JMP Script Files|jsl", "All Files|*"},
		1,
		1,
		"Layer_Settings.jsl"
	);

	Save Text File(VarsSavePath, As JSON Expr(settingsAA));
);

//expr open a jsl file, parse JSON into an AA and extract saved values
ImportVarsExpr = expr(
	VarsImportPath = Pick File(
		"Select jsl file that contains the saved parameters",
		SelfPath,
		{"JMP Script Files|jsl", "All Files|*"},
		1,
		0,
		""
	);

	loaded_settingsAA = Parse JSON(Load Text File(VarsImportPath));

	//for each element of AA, get the name of the element and set a variable with that name to the AA value
	for each({varname}, loaded_settingsAA,
		eval(parse(Evalinsert("\[  "^varname^"n = loaded_settingsAA << get value (varname) ]\")));
		//show(varname);
		//show(loaded_settingsAA << get value (varname));
	);
);

//show original variables
Write("\!N", "Original:");
show(var1, var2, var2);

//export variables
eval(ExportVarsExpr);

//clear the variables
var1 = .;
var2 = .;
var3 = .;
Write("\!N", "\!N", "Variables cleared:");
show(var1, var2, var2);

//import variables
eval(ImportVarsExpr);

//show that the variables have been imported
Write("\!N", "\!N", "Post loading:");
show(var1, var2, var2);

View solution in original post

3 REPLIES 3
txnelson
Super User

Re: Saving a new script to preserve variables for later

I am not sure how universal this is, but it does work on your simple script

names default to here (1);

//namespace for the shared variables
If( !Namespace Exists( "TestNS" ), New Namespace( "TestNS" ) );

//the variables I want to save for later
TestNS:a = 5;
TestNS:b = "text";
TestNS:c = {1,2,3,4};
TestNS:d = {"a","b","c","d"};

//set up script to save as JSL
script = expr( 	
	TestNS:a = a_dv;
	TestNS:b = b_dv;
	TestNS:c = c_dv;
	TestNS:d = d_dv;
);

//substitute the dummy values for the current values... this isn't working
substitute Into (script, expr(a_dv), nameexpr (TestNS:a));
substitute Into (script, expr(b_dv), nameexpr (TestNS:b));
substitute Into (script, expr(c_dv), nameexpr (TestNS:c));
substitute Into (script, expr(d_dv), nameexpr (TestNS:d));

// Move the arguments in the script to a character string
theScript = "";
i=1;
While( char(arg(script,i)) !="Empty()",
	theScript = theScript || char(arg(script,i)) || ";";
	i++;
);

show(script);

//save script for later use
Save Text File( "$downloads\MyScript.jsl", theScript );
Jim
jthi
Super User

Re: Saving a new script to preserve variables for later

Have you maybe consider storing those values into a associative array? It is most likely easier to manage and it can be saved for example as a JSON if needed.

 

Names Default To Here(1);

//namespace for the shared variables
If(!Namespace Exists("TestNS"),
	New Namespace(
		"TestNS"
	)
);

//the variables I want to save for later
TestNS:settings = Associative Array();
TestNS:settings["a"] = 5;
TestNS:settings["b"] = "text";
TestNS:settings["c"] = [1 2 3 4];
TestNS:settings["d"] = {"a", "b", "c", "d"};
TestNS:settings["e"] = ["key" => 1];


/*
TestNS:settings["a"] = cur_settings["a"];
TestNS:settings["b"] = cur_settings["b"];
TestNS:settings["c"] = cur_settings["c"];
TestNS:settings["d"] = cur_settings["d"];
TestNS:settings["e"] = cur_settings["e"];
*/

myfilepath = Save Text File("$DOWNLOADS/myscript.jsl", As JSON Expr(TestNS:settings));

conf = Load Text File(myfilepath);
loaded_settings = Parse JSON(conf);

You could then create few functions such as save_settings, load_settings, ... if needed.

-Jarmo
CitizenNo3
Level II

Re: Saving a new script to preserve variables for later

Thanks to both Jarmo and Jim, both those solutions work. I initially used Jim's solution, which was able to plug directly into what I initially had. After some revision, I adapted Jarmo's idea which indeed was tidier to manage. Here is what I ended up with. With this setup I didn't need the namespace, but it would still work with namespaces.

 

names default to here (1);

//initialize variables
var1 = {"a", "b", "c"};
var2 = 100;
var3 = [1, 2, 3, 4];

//initialize variables used for functions
VarsToExport = {"var1", "var2", "var3"};
SettingsAA = Associative Array();
loaded_settingsAA = .;
SelfPath = Get Default Directory();

//expr to get each variable in the VarsToExport list and input the value into an AA, export as JSON
ExportVarsExpr = expr(
	for each({varname}, VarsToExport,
		//show(varname);
		SettingsAA[varname] = eval(as name(varname));
		//show(SettingsAA);
	);
	
	VarsSavePath = Pick File(
		"Save a file containing current script settings",
		SelfPath,
		{"JMP Script Files|jsl", "All Files|*"},
		1,
		1,
		"Layer_Settings.jsl"
	);

	Save Text File(VarsSavePath, As JSON Expr(settingsAA));
);

//expr open a jsl file, parse JSON into an AA and extract saved values
ImportVarsExpr = expr(
	VarsImportPath = Pick File(
		"Select jsl file that contains the saved parameters",
		SelfPath,
		{"JMP Script Files|jsl", "All Files|*"},
		1,
		0,
		""
	);

	loaded_settingsAA = Parse JSON(Load Text File(VarsImportPath));

	//for each element of AA, get the name of the element and set a variable with that name to the AA value
	for each({varname}, loaded_settingsAA,
		eval(parse(Evalinsert("\[  "^varname^"n = loaded_settingsAA << get value (varname) ]\")));
		//show(varname);
		//show(loaded_settingsAA << get value (varname));
	);
);

//show original variables
Write("\!N", "Original:");
show(var1, var2, var2);

//export variables
eval(ExportVarsExpr);

//clear the variables
var1 = .;
var2 = .;
var3 = .;
Write("\!N", "\!N", "Variables cleared:");
show(var1, var2, var2);

//import variables
eval(ImportVarsExpr);

//show that the variables have been imported
Write("\!N", "\!N", "Post loading:");
show(var1, var2, var2);