main.BasePluginDispatcher: Static method to start a BASE plugin

Description Usage Arguments Value How an R BASE plugin is run Memory optimization Exception handling Creating a new plugin About the *.R source files Install R packages locally at the plugin directory About the file progress bar Author(s)

Description

Static method to start a BASE plugin.

Briefly, all R source files found in the plugin path are sourced and onRun(), which should be defined in one of the files, is called. Passed to onRun() is a BaseFile object for simple acccess to data sent form BASE, plus the plugin parameters sent from BASE. Data returned will automatically be save to file to be incorporated automatically by BASE.

Usage

1
BasePluginDispatcher$main(pluginPath=NULL, logDetails=-99, parametersSection=c("^parameters$", "settings$"), ...)

Arguments

pluginPath

A character string of the path to the plugin where the R source files for the plugin is. For conveniency, it may also be the pathname of a file in that directory. Typically, this should be same same directory as where the calling runBaseFile script is located. If NULL, the current directory is used.

logDetails

A numeric value. The smaller (negative), the more detailed the log output will be. If zero, no logging will take place. See Verbose for details. The log is written to file 'plugin.log'.

parametersSection

A character vector of regular expression patterns matching the label of the BASE section in which plugin parameters are stored.

...

Additional arguments used for testing the plugin. For instance, using stdin="stdin.txt" will make the plugin to read BASE file data from file "stdin.txt" instead of system's standard input. Similarily, stdout and stderr can be set to files. These and other arguments are not listed in the function definition in order to minimize misuse/mistakes. Experts may look at the source code for other arguments.

Value

Returns (invisibly) the result from onRun() as a BaseFile if returned, otherwise NULL.

How an R BASE plugin is run

It is important to know is that BASE runs a plugin in it own unique directory, which is the current directory. All files referred to below are created in this directory.

The plugin is run as follows:

  1. The working directory is set according to workPath. All files are created in this path.

  2. Log message are directed to file 'plugin.log'.

  3. A file progress bar named 'plugin.progress' is created. The size (in bytes) corresponds to 0-100% progress.

  4. All *.R files in the pluginPath are sourced.

  5. BASE data is read from standard input into a BaseFile object. As soon as the 'plugin parameters' section is read:

    1. If the plugin parameter sourcePath is set, the path is sourced for additional *.R source files.

    2. The onParameters() function is called, allowing for early parameters validation and coersion.

    3. The rest of the BASE file structure such as spots sections containing actually spot data is parsed/read. In order to minimize memory usage, each spot data table is cached to a seperate file and only read into memory upon request.

  6. Optional plugin parameters are extracted from this object. The BASE file section containing the parameters is removed and the resulting BaseFile object is called data.

  7. The plugin calls

    result <- onRun(data, <plugin parameters>)

    All plugin parameters are passed as name arguments, e.g. pluginVersion="1.0" etc.

  8. When onRun(), and possibly onError(), returns, onFinally() is called with same arguments as onRun().

  9. The result object is coerced to a BaseFile object. If successful, it is save as a BASE file named 'result.base', otherwise 'result.txt'.

Memory optimization

When reading the BASE file, the spot data tables for all array are automatically cached to seperate files without being read into R's memory. The data is read into memory first when getData() is called on a BaseFileSpots object. This makes it possible to pass virtually any number of arrays to an aroma.Base plugin.

The aboves makes it extremely easy to apply array-by-array algorithms. For example,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    onRun <- function(data, ...) {
      # For each spot section in the BASE file
      spotSections <- getSections(data, "spots");
      for (spotSection in spotSections) {
        # Get data table (automatically from temporary cached file)
        X <- getData(spotSection, fields=signalFields);
		 
        # Process data
        ...
        # Remove data from memory (but it still remains on file)
        rm(X); gc();
      }
    } # onRun()
   

When the plugin finishes, aroma.Base automatically cleans out all internally cached data files.

Exception handling

All errors are caught to avoid sudden interrupts, but the error messages are sent to system's standard error. Most of them are also logged to the log file.

If an error occurs when running onRun(), it is caught and onError() is called with the caught exception error as the first arguments, plus the arguments that was passed to onRun().

Exception generated by onError() and onFinally() are ignored but logged.

Creating a new plugin

  1. Create a new plugin directory, e.g. '~<user>/plugins/normalizeAffine/'.

  2. Copy the runBasePluginDispatcher Unix shell script to this directory.

  3. Copy all your *.R files to this directory, including 'onRun.R' that defines onRun().

  4. Define the plugin on BASE plugin definition page. Use '<path-to-user>/normalizeAffine/runBasePluginDispatcher' as the 'execName'.

  5. Make sure that all packages required are installed. You can install missing R packages in '~<user>/plugins/library/'.

The onRun() function must accept a BaseFile object as the first argument and the optional plugin parameteters as named arguments. Extra debug arguments may also be passed, which is why the function should also accept these, which can be done by adding ... to the list of arguments. Moreover, the Verbose object log and the ProgressBar object progress is available to all onNNN() functions. Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   onRun <- function(data, constraint=0.05, pluginVersion="1.0", ...) {
     log && enter(log, "Affine normalization of data");
     on.exit(log && exit(log, "Affine normalization of data"));

     # Plugin parameters are passed as strings from BASE
     contstraint <- as.double(constraint);

     # Gets reference variables to the different 'spots' sections
     spots <- getSections(data, "spots")
     for (spot in spots) {
       # Get signals
       fields <- c("intensity1", "intensity2");
       X <- getData(spot, fields=fields);
       X <- as.matrix(X);

       # Normalize
       X <- normalizeAffine(X);

       # Update data
       colnames(X) <- fields;
       setDataFields(spot, values=X);
     }

     # Return the modified 'spots' section
     spots;
   } # onRun()
  

Note that data is already read from standard input and are very easy to access via the methods of BaseFile.

For plugins that tranforms data, it is easiest to modify the actual data object and return it, because it typically already have the correct structure.

About the *.R source files

The *.R files in the plugin directory should only define functions and possible some object, but not do any processing; the R code should not be started until onRun() is called.

Note that onRun() must be defined in one of the *.R files, otherwise an exception is thrown saying so and the plugin fails to run. We recommend that onRun() is defined in 'onRun.R'.

Optionally, onError() and onFinally() can be defined similarily.

Install R packages locally at the plugin directory

When started, this method checks for optional R package libraries in directories named 'library/' in the parent directory of the pluginPath. If found, it is added at the beginning of the list of package libraries that R knowns of. That is, one can install missing/out-of-date packages in <pluginPath>/../library/ so that they can be loaded in onRun().

You can add additional library paths in one of your *.R files, e.g. in '000.R'. See ?.libPaths for more details.

About the file progress bar

Reporting the plugin progress to file by file size has the advantange that it is possible to view the progress via the file system, say, by ftp or ssh, and by just listing the files. No files have to be opened. It is even be possible to report the progress back to the BASE user interface, iff BASE would support/look for it.

When the plugin is started, the progress is set to 0%. When standard input has been read it is 1%, when all script files have been sourced it is 2%, then it is up to onRun() to either call increase(progress) or setProgress(progess, <fraction>) to bring the progess up to 97% before returning. See ?ProgressBar for details. When onRun() is completed, the progress is set to 98%, when onFinally() is completed it is set to 99%. When the results has been written to file (optional), it is set to 100%.

Author(s)

Henrik Bengtsson (http://www.braju.com/R/)


HenrikBengtsson/aroma.Base documentation built on May 7, 2019, 1:51 a.m.