Querying R for information

In some cases, you may want to fetch further information from R, to be presented in your plugin's UI. For instance, you may want to offer a selection of the levels of a factor that the user has selected for analysis. Since version 0.6.2 of RKWard it is possible to do so. Before we start, it is important that you are aware of some caveats:

R Code run from inside the plugin's UI logic is evaluated in R's event loop, meaning they can be run while other computations are running. This is to make sure your plugin's UI will be usable, even while R is busy doing other things. However, this makes it really important, that your code does not have side effects. In particular:

  • Do not make any assignments in .GlobalEnv or any other non-local environment.

  • Do not print anything to the output file.

  • Do not plot anything on-screen.

  • In general, do not do anything that has side-effects. Your code may read in information, not "do" anything.

With this in mind, here is the general pattern. You will use this inside a scripted UI logic section:

		<script><![CDATA[
				last_command_id = -1;
				gui.addChangeCommand ("variable", "update ()");
				update = function () {
					gui.setValue ("selector.enabled", 0);
					variable = gui.getValue ("variable");
					if (variable == "") return;

					last_command_id = doRCommand ('levels (' + variable + ')', "commandFinished");
				}

				commandFinished = function (result, id) {
					if (id != last_command_id) return;  // another result is about to arrive
					if (typeof (result) == "undefined") {
						gui.setListValue ("selector.available", Array ("ERROR"));
						return;
					}
					gui.setValue ("selector.enabled", 1);
					gui.setListValue ("selector.available", result);
				}
		]]></script>
	

Here, variable is a property holding an object name (e.g. inside a <varslot>). Whenever that changes, you will want to update the display of levels inside the <valueselector>, named selector. The key function here is doRCommand(), taking as first parameter the command string to run, and as second parameter the name of a function to call, when the command has finished. Note that the command is running asynchronously, and this makes things a bit more complex. For one thing you want to make sure, that your <valueselector> remains disabled, while it does not contain up-to-date information. Another thing is that you could potentially have queued more than one command, before you get the first results. This is why every command is given an "id", and we store that in last_command_id for later reference.

When the command is done, the specified callback is called (commandFinished, in this case) with two parameters: The result itself, and the id of the corresponding command. The result will be of a type resembling the representation in R, i.e. a numeric Array, if the result is numeric, etc. It can even be an R list(), but in this case it will be represented as a JS Array() without names.

Note that even this example is somewhat simplified. In reality you should take additional precautions, e.g. to avoid putting an extreme amount of levels into the selector. The good news is that probably you do not have to do all this yourself. The above example is taken from the rkward::level_select plugin, for instance, which you can simply embed in your own plugin. This even allows you to specify a different expression to run in place of levels().