[rkward-cvs] rkward/doc/en menu_hierarchy_example.png,NONE,1.1 t_test_plugin_example.png,NONE,1.1 Makefile.am,1.2,1.3 writing_plugins_introduction.docbook,1.1,1.2

Thomas Friedrichsmeier tfry at users.sourceforge.net
Wed Mar 22 17:10:40 UTC 2006


Update of /cvsroot/rkward/rkward/doc/en
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21174

Modified Files:
	Makefile.am writing_plugins_introduction.docbook 
Added Files:
	menu_hierarchy_example.png t_test_plugin_example.png 
Log Message:
Progress on plugin documentation

--- NEW FILE: menu_hierarchy_example.png ---
(This appears to be a binary file; contents omitted.)

Index: Makefile.am
===================================================================
RCS file: /cvsroot/rkward/rkward/doc/en/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** Makefile.am	21 Mar 2006 18:13:15 -0000	1.2
--- Makefile.am	22 Mar 2006 17:10:37 -0000	1.3
***************
*** 1,3 ****
! EXTRA_DIST = index.docbook writing_plugins_introduction.docbook
  
  KDE_LANG = en
--- 1,4 ----
! EXTRA_DIST = index.docbook writing_plugins_introduction.docbook menu_hierarchy_example.png \
! 	t_test_plugin_example.png
  
  KDE_LANG = en

--- NEW FILE: t_test_plugin_example.png ---
(This appears to be a binary file; contents omitted.)

Index: writing_plugins_introduction.docbook
===================================================================
RCS file: /cvsroot/rkward/rkward/doc/en/writing_plugins_introduction.docbook,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** writing_plugins_introduction.docbook	21 Mar 2006 18:13:16 -0000	1.1
--- writing_plugins_introduction.docbook	22 Mar 2006 17:10:38 -0000	1.2
***************
*** 22,26 ****
  <author>
  <firstname>Thomas</firstname>
! <surname>Freidrichsmeier</surname>
  <affiliation>
  <address><email>tfry AT users DOT sourceforge DOT net</email></address>
--- 22,26 ----
  <author>
  <firstname>Thomas</firstname>
! <surname>Friedrichsmeier</surname>
  <affiliation>
  <address><email>tfry AT users DOT sourceforge DOT net</email></address>
***************
*** 33,37 ****
  <copyright>
  <year>2006</year>
! <holder>George N. Ugnacious</holder>
  </copyright>
  <!-- Translators: put here the copyright notice of the translation -->
--- 33,37 ----
  <copyright>
  <year>2006</year>
! <holder>Thomas Friedrichsmeier</holder>
  </copyright>
  <!-- Translators: put here the copyright notice of the translation -->
***************
*** 94,111 ****
  </chapter>
  
  <chapter id="pluginmap">
  <title>Creating menu entries</title>
  </chapter>
  
  <chapter id="mainxml">
  <title>Defining the GUI</title>
  </chapter>
  
! <chapter id="what_are_plugins">
  <title>Generating R code from GUI settings</title>
  </chapter>
  
  <chapter id="logic">
  <title>GUI logic</title>
  </chapter>
  
--- 94,471 ----
  </chapter>
  
+ <chapter id="whatareplugins">
+ <title>Preliminaries: What are plugins in &kapp;? How do they work?</title>
+ <para>
+ Of course the first question you might have is: What portions of &kapp; functionality is realized using plugins? Or: What can plugins do?
+ </para>
+ <para>
+ One way to answer this is: Deselect all .pluginmap-files under Settings->Configure &kapp;->Plugins, and see what's missing. A slightly more helpful answer: Most acutal statistics functions accessable via the GUI are realized using plugins. Also, you can create fairly flexible GUIs for all kinds of operations using plugins.
+ </para>
+ <para>
+ The basic paradigm behind &kapp; plugins is the one we'll walk you through in this document: An xml-file describes what the GUI looks like. An additional PHP-file is used to generate R syntax from the GUI settings. That is, plugins do not really have to perform any statistical calculations. Rather plugins generate the R syntax needed to run those calculations. The R syntax is then sent to the R backend for evaluation, and typically a result is shown in the output window.
+ </para>
+ <para>
+ Read on in the next chapters to see how this is done.
+ </para>
+ </chapter>
+ 
  <chapter id="pluginmap">
  <title>Creating menu entries</title>
+ <para>
+ When you create a new plugin, you need to tell &kapp; about it. So the first thing to do, is to write a .pluginmap-file (or modify an existing one). The format of .pluginmap is XML. I'll walk you through an example (also of course, be sure you have &kapp; configured to load your pluginmap – Settings->Configure &kapp;->Plugins):
+ </para>
+ <programlisting>
+ <!DOCTYPE rkpluginmap>
+ </programlisting>
+ <para>
+ The doctype is not really interpreted, but set it to “rkpluginmap” anyway.
+ </para>
+ <programlisting>
+ <document base_prefix="" namespace="rkward">
+ </programlisting>
+ <para>
+ The “base_prefix”-attribute can be used, if all your plugins reside in a common directory. Basically, then, you can omit that directory from the filenames specified below. As you will see below, all plugins get a unique identifier. The “namespace” is a way to organized those ids, and make it less likely to create a duplicate identifier accidentally. Internally, basically the namespace and then a “::” gets prepended to all the identifiers you specify below.
+ </para>
+ <programlisting>
+ 	<components>
+ </programlisting>
+ <para>
+ Components? Aren't we talking about plugins? Yes, but in the future, plugins will be no more than a special class of components. What we do here, then, is to register all components/plugins with &kapp;. Let's look at an example entry:
+ </para>
+ <programlisting>
+ 		<component type="standard" id="independent_samples_t_test" file="means/ttests/independent_samples.xml" label="Independent Samples" />
+ </programlisting>
+ <para>
+ First the “type”-attribute: Leave this to “standard” for now. Further types are not yet implemented. The “id” I've already hinted at. Each component has to be given a unique (in its namespace) identifier. Pick one that is easily recognizable. Avoid spaces and any special characters. Those are not banned, so far, but might have special meanings. With the “file” attribute, you specify where the <link linkend="mainxml">description of the actual plugin itself</link> is located. This is relative to the directory the .pluginmap-file is in, and the “base_prefix” above. Finally, give the component a label. This label will be shown whereever the plugin is placed in the menu (or in the future perhaps in other places as well).
+ </para>
+ <para>
+ Typically a .pluginmap-file will contain several components, so here are a few more:
+ </para>
+ <programlisting>
+ 		<component type="standard" id="unimplemented_test" file="means/unimplemented.xml" />
+ 		<component type="standard" id="fictional_t_test" file="means/ttests/fictional.xml" label="This is a fictional t-test" />
+ 		<component type="standard" id="descriptive" file="descriptive.xml" label="Descriptive Statistics" />
+ 		<component type="standard" id="corr_matrix" file="corr_matrix.xml" label="Correlation Matrix" />
+ 		<component type="standard" id="simple_anova" file="simple_anova.xml" label="Simple Anova" />
+ 	</components>
+ </programlisting>
+ <para>
+ Ok, this was the first step. &kapp; now knows those plugins exist. But how to invoke them? They need to be placed in a menu-hierarchy:
+ </para>
+ <programlisting>
+ 	<hierarchy>
+ 		<menu id="analysis" label="Analysis" index="4">
+ </programlisting>
+ <para>
+ Right below the <hierarchy>-tag, you start describing, in which menu, your plugins should go. With the above line, you basically say, that your plugin should be in the “Analysis” menu (not necessarily directly there, but in a submenu). The “Analysis” menu is standard in &kapp;, so it does not acutally have to be created from scratch. However, if it did not exist yet, using the “label”-attribute you'd give it its name. The “index” attribute says, that the menu (if newly created) should be placed at the fourth position in the menubar.
+ Finally, the “id” once again identifies this menu. This is needed, so several .pluginmap-files can place their plugins in the same menus. They do this by looking for a menu with the given “id”. If the id does not yet exist, a new menu will be created. Otherwise the entries will be added to the existing menu.
+ </para>
+ <programlisting>
+ 			<menu id="means" label="Means" index="1">
+ </programlisting>
+ <para>
+ Basically the same thing here: Now we define a submenu to the “Analysis”-menu. It is to be called “Means”.
+ </para>
+ <programlisting>
+ 				<menu id="ttests" label="T-Tests">
+ </programlisting>
+ <para>
+ And a final level in the menu-hierarchy: A sub-menu of the sub-menu “Means”. Note, that if you omit the “index” parameter, the new entry will be placed below any already existing ones.
+ </para>
+ <programlisting>
+ 					<entry component="independent_samples_t_test" />
+ </programlisting>
+ <para>
+ Now, finally, this is the menu, we want to place the plugin in. The <entry>-tag signals, this actually is the real thing, instead of another submenu. The “component”-attribute refers to the “id” you gave the plugin/component above.
+ </para>
+ <programlisting>
+ 					<entry component="fictional_t_test" />
+ 				</menu>
+ 				<entry component="fictional_t_test" />
+ 			</menu>
+ 			<menu id=”frequency” label=”Frequency” index=”2”/>
+ </programlisting>
+ <para>
+ In case you have lost track: This is another submenu to the “Analysis” menu. See the screenshot below. We'll skip some of what's not visible, marked with [...].
+ </para>
+ <programlisting>
+ 				[...]
+ 			</menu>
+ 			<entry component="corr_matrix" index="4"/>
+ 			<entry component="descriptive" index="3"/>
+ 			<entry component="simple_anova" index="5"/>
+ 		</menu>
+ </programlisting>
+ <para>
+ These are the final entries visible in the screenshots below. Note, that you don't need to define the entries in the order they should have in the menu. Use the “index”-attribute instead.
+ </para>
+ <programlisting>
+ 		<menu id="plots" label="Plots" index="5">
+ 			[...]
+ 		</menu>
+ </programlisting>
+ <para>
+ Of course you can also place your plugins in menus other than “Analysis”.
+ </para>
+ <programlisting>
+ 		<menu id="file" label="File" index="0">
+ 			[...]
+ 		</menu>
+ </programlisting>
+ <para>
+ Even in standard-menus such as “File”. All you need is the correct “id”.
+ </para>
+ <programlisting>
+ 	</hierarchy>	
+ </document>
+ </programlisting>
+ <para>
+ That's how to do it. And this screenshot shows the result:
+ </para>
+ <screenshot>
+ <screeninfo>Menu hierarchy created by the code shown above</screeninfo>
+ 	<mediaobject>
+ 	  <imageobject>
+ 	    <imagedata fileref="menu_hierarchy_example.png" format="PNG"/>
+ 	  </imageobject>
+ 	  <textobject>
+ 	    <phrase>Menu hierarchy created by the code shown above</phrase>
+ 	  </textobject>
+ 	</mediaobject>
+ </screenshot>
+ <para>
+ Confused? The easiest way to get started is probably taking some of the existing .plugin_map files shipped with the distribution, and modifying them to your needs. Also, if you need help, don't hesitate to write to the development mailing list.
+ </para>
  </chapter>
  
  <chapter id="mainxml">
  <title>Defining the GUI</title>
+ <para>
+ In the <link linked="pluginmap">previous chapter</link> you've seen how to register a plugin with &kapp;. The most important ingredient was specifying the path to an XML file with a description of what the plugin actually looks like. In this chapter you'll learn how to create this XML file.
+ </para>
+ <para>
+ Once again we'll walk you through an example. The example is a (slightly simplified) version of the independent samples t-test.
+ </para>
+ <programlisting>
+ <!DOCTYPE rkplugin>
+ </programlisting>
+ <para>
+ The doctype is not really interpreted, yet. Set it to rkplugin, anyway.
+ </para>
+ <programlisting>
+ <document>
+ 	<code file=”code.php”/>
+ </programlisting>
+ <para>
+ All plugins generate some code. Currently the only way to do so is using PHP, as detailed in <link linkend="phptemplate">the next chapter</link>. This defines, where to look for the PHP-code. The filname is relative to the directory the plugin-xml is in.
+ </para>
+ <programlisting>
+ 	<dialog label=”Independent Samples T-Test”>
+ </programlisting>
+ <para>
+ As you know, plugins may have either a dialog or a wizard-interface or both. Here we start definining a dialog-interface. the label-attribute specifies the caption of the dialog.
+ </para>
+ <programlisting>
+ 		<tabbook>
+ 			<tab label="Basic settings">
+ </programlisting>
+ <para>
+ GUI-elements can be organized using a tabbook. Here we define a tabbook as the first element in the dialog. Use <tabbook>[...]</tabbook> to define the tabbook and then for each page in the tabbook use <tab>[...]</tab>. The “label”-attribute in the <tab>-element allows you to specify a caption for that page of the tabbook.
+ </para>
+ <programlisting>
+ 				<row>
+ </programlisting>
+ <para>
+ The <row> and <column> tags specify the layout of the GUI elements. Here you say, that you'd like to place some elements side-by-side (left to right) and the first of these elements is to be a:
+ </para>
+ <programlisting>
+ 					<varselector id="vars"/>
+ </programlisting>
+ <para>
+ Using this simple tag you create a list from which the user can select variables. You have to specify an id for this element, so RKWard knows how to find it. Note that you may NOT use a dot (.) in the “id” string.
+ </para>
+ <programlisting>
+ 					<column>
+ </programlisting>
+ <para>
+ Next, we nest a <column> inside the row. I.e. the following elements will be place above each other (top-to-bottom), and all will be to the right of the <varselector>.
+ </para>
+ <programlisting>
+ 						<varslot type="numeric" id="x" source="vars" required="true" label="compare"/>
+ 						<varslot type="numeric" id="y" source="vars" required="true" label="against"/>
+ </programlisting>
+ <para>
+ These elements are the counterpart to the <varselector>. They represent “slots” into which the user can put variables. You will note that the “source” is set to the same value as the “id” of the <varselector>. This means, the <varslot>s will each take their variables from the varselector. The <varslot>s also have to be given an “id”. They may have a label, and they may be set to “required”. This means that the submit-button will not be enabled until the <varslot> holds a valid value. Finally the “type”-attribute is not interpreted, yet, but it will be used to take care that only the correct types of variables will be allowed in the <varslot>.
+ </para>
+ <programlisting>
+ 						<radio id="hypothesis" label="using test hypothesis">
+ 							<option value="two.sided" label="Two-sided"/>
+ 							<option value="greater" label="First is greater"/>
+ 							<option value="less" label="Second is greater"/>
+ 						</radio>
+ </programlisting>
+ <para>
+ Here, you define a group of <radio>-exclusive buttons. The group has a “label” and an “id”. Each <option> (button) has a label and is assigned a value. This is the value the <radio>-element will return when the option is selected.
+ </para>
+ <programlisting>
+ 					</column>
+ 				</row>
+ 			</tab>
+ </programlisting>
+ <para>
+ Each tag has to be closed. We've put all the elements we wanted (the two <varslots> and the <radio>) in the <column>. We put all elements we wanted (the <varselector> and the <column> with those elements) in the <row>. And we've put all the elements we wanted into the first page in the <tabbook>. We're not yet done defining the <tabbook> (more pages to come) and of course there's more to come in the <dialog>, too. But this screenshot is basically what we've done so far:
+ </para>
+ <screenshot>
+ <screeninfo>T test plugin</screeninfo>
+ 	<mediaobject>
+ 	  <imageobject>
+ 	    <imagedata fileref="t_test_plugin_example.png" format="PNG"/>
+ 	  </imageobject>
+ 	  <textobject>
+ 	    <phrase>T test plugin</phrase>
+ 	  </textobject>
+ 	</mediaobject>
+ </screenshot>
+ <para>
+ Note that we have not specified the “Submit”, “Close”, etc. buttons or the code-view. Those elements get generated automatically. But of course we still have to define the second page of the <tabbook>:
+ </para>
+ <programlisting>
+ 			<tab label="Options">
+ 				<checkbox id="varequal" label="assume equal variances" value=", var.equal=TRUE"/>
+ </programlisting>
+ <para>
+ By default elements will be placed top-to-bottom like in a <column>. Since that is what we want here, we don't have to explicitly state a <row> or <column>-layout. The first element we define is a checkbox. Just like the <radio><option>s, the checkbox has a “label” and a “value”. The “value” is what gets returned, if the checkbox is checked. Of course the checkbox also needs an “id”.
+ </para>
+ <programlisting>
+ 				<frame label="Confidence Interval">
+ </programlisting>
+ <para>
+ Here's yet another layout-element: In order to signal that the two elements below  belong together, we draw a <frame> (box). That frame may have a caption. Since the frame is just a passive layout-element, it does not need an “id”.
+ </para>
+ <programlisting>
+ 					<checkbox id="confint" label="print confidence interval" value="1" checked="true"/>
+ 					<spinbox type="real" id="conflevel" label="confidence level" min="0" max="1" initial="0.95"/>
+ 				</frame>
+ </programlisting>
+ <para>
+ Inside the <frame> we place another <checkbox> (using checked=”true”, we signal that checkbox should be checked by default), and a <spinbox>. The spinbox allows the user to select a value between “min” and “max” with the default/initial value “0.95”. Setting the “type” to “real” signals that real number are accepted as opposed to type=”integer” which would accept integers only.
+ </para>
+ <programlisting>
+ 			</tab>
+ 		</tabbook>
+ 	</dialog>
+ </programlisting>
+ <para>
+ That all for the second page of the <tabbook>, all pages in the <tabbook> and all elements in the <dialog>. We're finished defining what the dialog looks like. Actually we don't have to define an additional <wizard>-interface, but here's how that would be done. Things should be fairly self-explanatory be now, so I leave that part without comments:
+ </para>
+ <programlisting>
+ 	<wizard label=”Independent Samples T-Test”>
+ 		<page id="firstpage">
+ 			<text>As a first step, select the two variables you want to compare against each other. And specify, which one you theorize to be greater. Select two-sided, if your theory does not tell you, which variable is greater.</text>
+ 			<row>
+ 				<column>
+ 					<varselector id="vars"/>
+ 				</column>
+ 				<column>
+ 					<varslot type="numeric" id="x" source="vars" required="true" label="compare"/>
+ 					<varslot type="numeric" id="y" source="vars" required="true" label="against"/>
+ 					<radio id="hypothesis" label="using test hypothesis">
+ 						<option value="two.sided" label="Two-sided"/>
+ 						<option value="greater" label="First is greater"/>
+ 						<option value="less" label="Second is greater"/>
+ 					</radio>
+ 				</column>
+ 			</row>
+ 		</page>
+ 		<page id="secondpage">
+ 			<text>Below are some advanced options. It's generally safe not to assume the variables have equal variances. An appropriate correction will be applied then. Chosing "assume equal variances" may increase test-strength, however.</text>
+ 			<checkbox id="varequal" label="assume equal variances" value=", var.equal=TRUE"/>
+ 			<text>Sometimes it's helpful to get an estimate of the confidence interval of the difference in means. Below you can specify whether one should be shown, and which confidence-level should be applied (95% corresponds to a 5% level of significance).</text>
+ 			<frame label="Confidence Interval">
+ 				<checkbox id="confint" label="print confidence interval" value="1" checked="true"/>
+ 				<spinbox type="real" id="conflevel" label="confidence level" min="0" max="1" initial="0.95"/>
+ 			</frame>
+ 		</page>
+ 	</wizard>
+ </programlisting>
+ <para>
+ As you see, all of this is mostly a duplication of what has been defined for the dialog-interface. You may of course make the wizard-interface look very different to the plain dialog. Be sure, however, to assign corresponding elements the same "id" in both interfaces. This is not only used to transfer settings from the dialog-interface to the wizard-interface and back, when the user switches interfaces (which does not yet happen in the current version of RKWard), but also simplifies writing your code-template (see below). 
+ </para>
+ <programlisting>
+ </document>
+ </programlisting>
+ <para>
+ Finally we close the <document>-tag, and that's it. The GUI is defined. You can save the file now. But how does R-syntax get generated from the GUI-settings? I'll deal with that next.
+ </para>
  </chapter>
  
! <chapter id="phptemplate">
  <title>Generating R code from GUI settings</title>
+ <para>
+ Now we have a GUI defined, but we still need to generate some R-code from that. For that, we need another text-file, “code.php”, located in the same directory as the <link linkend="mainxml">description.xml</link>. You may or may not be familiar with PHP. Documentation on PHP can be found here: http://www.php.net. But for most purposes you will not need to know much about PHP at all, as we'll only use some very basic features..
+ </para>
+ <para>
+ For the independent samples t-test, the code.php file looks as follows (with comments in between):
+ </para>
+ <programlisting>
+ <?
+ </programlisting>
+ <para>
+ This is a sort of opening tag in PHP. Everything between <? and ?> will be interpreted as PHP-code. Everything outside of these tags will simply be returned as plain text. See below for examples.
+ </para>
+ <programlisting>
+ 	function preprocess () {
+ 	}
+ </programlisting>
+ <para>
+ The PHP-file is organized into four separate functions: preprocess, calculate, printout and cleanup. This is because not all code is needed at all stages. Currently the preprocess-function is not really used.
+ </para>
+ <programlisting>
+ 	function calculate () {
+ ?>rk.temp <- t.test (<? getRK ("x"); ?>, <? getRK ("y"); ?>, "<? getRK ("hypothesis"); ?>"<? getRK (“varequal”); if (($conflevel = getRK_val ("conflevel")) != "0.95") echo (", conf.level=" . $conflevel); ?>)
+ <?
+ 	}
+ </programlisting>
+ <para>
+ This function generates the actual R-syntax to be run from the GUI-settings. Let's look at this in detail:
+ First we leave the PHP-mode (?>) and hence return
+ </para>
+ <screen>
+ “rk.temp <- t.test (“
+ </screen>
+ <para>
+ as plain text. Next we need to fill in the value, the user selected as the first variable. Hence we enter PHP-mode again (<?) and call 'getRK (“x”);'. This prints out the value of the GUI-element with id “x”: our first <varslot>. Next we leave PHP-mode again, print a ', ', and do the same to fetch the value of the element “y” - the second <varslot>. For the hypothesis (the <radio>-group), and the equal variances-<checkbox>, the procedure is very similar.
+ </para>
+ <para>
+ It gets a little more tricky for the confidence level. For reasons of aestethics, we don't want to explicitly specify the confidence level to use, if it corresponds to the default value. Hence, instead of printing the value with 'getRK', we fetch it silently using 'getRK_val' and assign it to a PHP-variable. We then check, whether that variable differs from “0.95” and if so print out an additional argument.
+ Finally, we leave PHP-mode again, print a last ')', and that's it for the calculate-function.
+ </para>
+ <programlisting>
+ 	function printout () {
+ <? rk.print (rk.temp); ?>
+ 	}
+ </programlisting>
+ <para>
+ And this was all there is to the printout function in most cases. rk.print utilizes the R2HTML package to provide HTML formatted output. You could also excert greater control over the generated output. For this, you'll generate an R syntax, that consists esp. of "cat ()" commands, piecing together an HTML output. If in doubt, just use rk.print (), and be done with.
+ </para>
+ <para>
+ Note: At the time of this writing, I plan to add an rk.print.header () function to print out some information about what kind of analysis was done, when, what parameters, etc. Check back with this document, soon.
+ </para>
+ <programlisting>
+ 	function cleanup () {
+ ?>rm (rk.temp)
+ <?
+ 	}
+ ?>
+ </programlisting>
+ <para>
+ Finally, in the function cleanup we discard the temporary object(s) we left in the R-workspace. You should always clean up all objects created while running the plugin, except the user explicitely requested otherwise.
+ </para>
  </chapter>
  
  <chapter id="logic">
  <title>GUI logic</title>
+ <para>
+ </para>
  </chapter>
  
***************
*** 114,134 ****
  <para>
  
- <!-- Note that all graphics should be in .png format. Use no gifs because of
- patent issues. -->
- 
- <screenshot>
- <screeninfo>Here's a screenshot of &kapp;</screeninfo>
- 	<mediaobject>
- 	  <imageobject>
- 	    <imagedata fileref="screenshot.png" format="PNG"/>
- 	  </imageobject>
- 	  <imageobject>
- 	    <imagedata fileref="screenshot.eps" format="EPS"/>
- 	  </imageobject>
- 	  <textobject>
- 	    <phrase>Screenshot</phrase>
- 	  </textobject>
- 	</mediaobject>
- </screenshot>
  </para>
  </chapter>
--- 474,477 ----
***************
*** 137,141 ****
  
  <appendix id="reference">
! <title>Installation</title>
  </appendix>
  
--- 480,484 ----
  
  <appendix id="reference">
! <title>Reference</title>
  </appendix>
  





More information about the rkward-tracker mailing list