Writing your own test

This section how to writing a simple plugin. In this example, we will create a test which filter spots with flag value at notfound. There is only one requirement to produce a functional plugin: it must contains one or more (a plugin can have more than one test) class witch extends QualityUnitTest() and implements the Module() interface.

The Module() interface force the developer to describe the module he want to add to doelan.

The abstract QualityUnitTest() impose you to set the parameters (name, type and default value) of test and wrinting a test() witch do the job.

The end of this section show you the annoted code of a test filtering spots with flag value at notfound. You'll find the source of this plugin and scripts to build it in the doc/plugin directory of doelan.

// Import Unit test class
import fr.ens.transcriptome.doelan.algorithms.QualityUnitTest;

// Import Result test classes
import fr.ens.transcriptome.doelan.data.QualityUnitTestResult;
import fr.ens.transcriptome.doelan.data.QualityUnitTestResult.SummaryResult;

// Import Module management classes
import fr.ens.transcriptome.nividic.platform.module.AboutModule;
import fr.ens.transcriptome.nividic.platform.module.Module;
import fr.ens.transcriptome.nividic.platform.module.ModuleDescription;
import fr.ens.transcriptome.nividic.platform.PlatformException;

// Import of the classes for handling bioassays
import fr.ens.transcriptome.nividic.om.BioAssay;
import fr.ens.transcriptome.nividic.om.SpotIterator;

// Import of the classes for handling parameters in a module
import fr.ens.transcriptome.nividic.util.parameter.FixedParameters;
import fr.ens.transcriptome.nividic.util.parameter.Parameter;
import fr.ens.transcriptome.nividic.util.parameter.ParameterBuilder;
import fr.ens.transcriptome.nividic.util.parameter.ParameterException;
import fr.ens.transcriptome.nividic.util.parameter.Parameters;

/**
 * Plugin Sample Test.
 * This class define a test based on not found spot flags.
 * @author Laurent Jourdren
 */
public class PluginSampleTest extends QualityUnitTest implements Module {

  /**
   * Get the description of the module.
   * The aboutModule() method allow to describe the test for the 
   * user in the doelan interface.
   * @return The description of the module
   */
  public AboutModule aboutModule() {

    ModuleDescription md = null;
    try {
      md = new ModuleDescription("PluginSampleTest",
          "Plugin sample Test : Test not found spot flag for BioAssay");
    } catch (RomdePlatformException e) {
      getLogger().error("Unable to create the module description");
    }
    return md;
  }

  /**
   * Set the parameters of the element.
   * The defineParameters() method allow to describe the type, 
   * the defaults values and the range of all parameters of the test. 
   * If the user enter enter in Doelan an out of range parameter, the 
   * message will tell him that parameter is wrong.
   * @return The defaults parameters to set.
   */
  protected Parameters defineParameters() {

    try {

      final Parameter threshold = new ParameterBuilder().withName("Threshold")
          .withType(Parameter.DATATYPE_DOUBLE).withDescription(
              "Threshold for the test").withGreaterThanValue(0)
              .withDefaultValue("0.10").getParameter();
      final Parameter filterFlags = new ParameterBuilder().withName(
              "Filter flags").withType(Parameter.DATATYPE_BOOLEAN)
              .withDescription(
              "Filter invalid features in output arraylist file")
              .withDefaultValue("false").getParameter();

      final FixedParameters params = new FixedParameters();
      params.addParameter(threshold);
      params.addParameter(filterFlags);

      return params;

    } catch (ParameterException e) {
      System.err.println(e);
    }

    return null;
  }

  /**
   * Test the quality of the bioassay.
   * @param bioassay BioAssay to test
   * @param arrayList The array list
   * @param parameters parameters of the test
   * The test() method is the main function of the test. There, the test will be executed.
   * @return A QualityObjectResultTest Object
   * @throws PlatformException if an error occurs while executing 
   * the test.
   */
  public QualityUnitTestResult test(final BioAssay bioassay,
      final BioAssay arrayList, final Parameters parameters)
      throws PlatformException {

    QualityUnitTestResult result = null;

    try {

      final boolean[] results = new boolean[bioassay.size()];
      final int[] flags = bioassay.getFlags();

      // Get the user parameters values
      final double threshold = parameters.getParameter("Threshold")
                               .getDoubleValue();
      final boolean filterFlags = parameters.getParameter("Filter flags")
                                  .getBooleanValue();

      int countNotFound = 0;
      int countRealSpot = 0;

      // Iterate over the bioassay to test all the flags of the spots
      SpotIterator si = bioassay.iterator();

      while (si.hasNext()) {
        si.next();

        if (si.isEmpty() || si.isFlagAbscent())
          continue;

        // If the flag of spot is not found, the spot if set to false in 
	// the results array and will not be in the output gal file
        if (si.getFlag() == BioAssay.FLAG_NOT_FOUND)
          countNotFound++;
        else
          results[si.getIndex()] = true;
    
        countRealSpot++;
      }
      
      
      final double ratio = ((double) countNotFound) / ((double) countRealSpot);

      // Set the result information in the result variable
      result = new QualityUnitTestResult(bioassay, this);
      result.setMessage("Not found flag features : " + countNotFound + " / "
          + countRealSpot + " max : " + (countRealSpot * threshold));

      result.setGlobalResultType(true);
      if (filterFlags) result.setNewFlags(results);
      
      SummaryResult rac = result.getResultAllChannels();
      rac.setPercent(true);
      rac.setThresholdEqualityType("<=");
      rac.setUnit("%");
      rac.setThreshold(threshold);
      rac.setValue(ratio);
      rac.setPass(ratio <= threshold);

    } catch (ParameterException e) {
      throw new PlatformException("Error while creating parameters ("
          + this.getClass().getName() + ") : " + e.getMessage());
    }

    // Return the result
    return result; 
  }

  //
  // Constructor
  //

  /**
   * Public constructor.
   * @throws PlatformException If the name or the version of the element 
   *         is null.
   */
  public PluginSampleTest() throws PlatformException {
    // MUST BE EMPTY
  }
}
  

Compliation and installation of plugins

This section presents you the process of building a functionnal plugin after writing the source code. All the next steps are very common, you can easily script it (with ant, unix or Windows shell). In the next chapter you'll find two scripts (one for *nix and one for Windows) to automate the building of a simple plugin. Wrinting an Ant script will be useful if you consider to develop a large plugin.

  • In your source directory compile your plugin. You can use a makefile like Ant to automate the compilation of your sources.
  • Pack the generated .class file in a .jar file.
  • Copy your .jar in the Doelan plugins directory.
  • Restart Doelan.
  • Now, You can use your own test in the application.

Building the plugin sample

This an script for building the .jar file of the plugin under *nix. Don't forget to replace PATH_TO_DOELAN by the valid path to Doelan on your filesystem in the script.

  
#!/bin/sh

DIRLIB=$PATH_TO_DOELAN/lib

for LIB in `ls $DIRLIB`
do
  CLASSPATH=$DIRLIB/$LIB:$CLASSPATH
done

rm *.class *.jar
javac -classpath $CLASSPATH *.java
jar cf testplugin.jar *.class
  

This is the same script for Windows. It's a batch file, save into a text file and rename it with the .bat extension. Be careful under Windows, with the CLASSPATH and PATH environement variable, sometimes they are not set. See your Java documentation for more information.

  
del *.class
del *.jar
javac -classpath %CLASSPATH% *.java
jar cf testplugin.jar *.class