A plug-in becomes an analysis plug-in simply by returning
Plugin.MainType.ANALYZE
from the
Plugin.getMainType()
method. The information returned from
InteractivePlugin.getGuiContexts()
must include: [Item.BIOASSAYSET
, Type.ITEM
]
since this is the main place where the web client looks for analysis plug-ins. If
the plug-in can work on a subset of the bioassays it may also include
[Item.BIOASSAY
, Type.LIST
]
among the contexts. This will make it possible for a user to select
bioassays from the list and then invoke the plug-in.
private static final Set<GuiContext> guiContexts = Collections.singleton(new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM)); public Set<GuiContext> getGuiContexts() { return guiContexts; }
If the plugin depends on a specific raw data type or on the number of
channels, it should check that the current bioassayset is of the
correct type in the InteractivePlugin.isInContext()
method. It is also a good idea to check if the current user has permission
to use the current experiment. This permission is needed to create new bioassaysets or
other data belonging to the experiment.
public boolean isInContext(GuiContext context, Object item) { if (item == null) { message = "The object is null"; } else if (!(item instanceof BioAssaySet)) { message = "The object is not a BioAssaySet: " + item; } else { BioAssaySet bas = (BioAssaySet)item; int channels = bas.getRawDataType().getChannels(); if (channels != 2) { message = "This plug-in requires 2-channel data, not " + channels + "-channel."; } else { Experiment e = bas.getExperiment(); e.checkPermission(Permission.USE); } } }
The plugin should always include a parameter asking for the current
bioassay set when the InteractivePlugin.getRequestInformation()
is called with command = Request.COMMAND_CONFIGURE_JOB
.
private static final RequestInformation configurePlugin; private RequestInformation configureJob; private PluginParameter<BioAssaySet> bioAssaySetParameter; public RequestInformation getRequestInformation(GuiContext context, String command) throws BaseException { RequestInformation requestInformation = null; if (command.equals(Request.COMMAND_CONFIGURE_PLUGIN)) { requestInformation = getConfigurePlugin(context); } else if (command.equals(Request.COMMAND_CONFIGURE_JOB)) { requestInformation = getConfigureJob(context); } return requestInformation; } private RequestInformation getConfigureJob(GuiContext context) { if (configureJob == null) { bioAssaySetParameter; = new PluginParameter<BioAssaySet>( "bioAssaySet", "Bioassay set", "The bioassay set used as the source for this analysis plugin", new ItemParameterType<BioAssaySet>(BioAssaySet.class, null, true, 1, null) ); List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>(); parameters.add(bioAssaySetParameter); // Add more plug-in-specific parameters here... configureJob = new RequestInformation( Request.COMMAND_CONFIGURE_JOB, "Configure job", "Set parameter for plug-in execution", parameters ); } return configureJob; }
Of course, the InteractivePlugin.configure()
method needs
to validate and store the bioassay set parameter as well:
public void configure(GuiContext context, Request request, Response response) { String command = request.getCommand(); try { if (command.equals(Request.COMMAND_CONFIGURE_PLUGIN)) { // Validate and store configuration parameters response.setDone("Plugin configuration complete"); } else if (command.equals(Request.COMMAND_CONFIGURE_JOB)) { List<Throwable> errors = validateRequestParameters(configureJob.getParameters(), request); if (errors != null) { response.setError(errors.size() + " invalid parameter(s) were found in the request", errors); return; } storeValue(job, request, bioAssaySetParameter); // Store other plugin-specific parameters response.setDone("Job configuration complete", Job.ExecutionTime.SHORT); } } catch (Throwable ex) { // Never throw exception, always set response! response.setError(ex.getMessage(), Arrays.asList(ex)); } }
Now, the typical Plugin.run()
method loads the specfied bioassay set
and its spot data. It may do some filtering and recalculation of the spot
intensity value(s). In most cases it will store the result as a child bioassay
set with one bioassay for each bioassay in the parent bioassay set.
Here is an example, which just copies the intensity values, while
removing those with a negative value in either channel.
public void run(Request request, Response response, ProgressReporter progress) { DbControl dc = sc.newDbControl(); try { BioAssaySet source = (BioAssaySet)job.getParameter("bioAssaySet"); // Reload with current DbControl source = BioAssaySet.getById(dc, source.getId()); int channels = source.getRawDataType().getChannels(); // Create transformation and new bioassay set Job j = Job.getById(dc, job.getId()); Transformation t = source.newTransformation(j); t.setName("Copy spot intensities >= 0"); dc.saveItem(t); BioAssaySet result = t.newProduct(null, "new", true); result.setName("After: Copying spot intensities"); dc.saveItem(result); // Get query for source data DynamicSpotQuery query = source.getSpotData(); // Do not return spots with intensities < 0 for (int ch = 1; ch <= channels; ++ch) { query.restrict( Restrictions.gteq( Dynamic.column(VirtualColumn.channel(ch)), Expressions.integer(0) ) ); } // Create batcher and copy data SpotBatcher batcher = result.getSpotBatcher(); int spotsCopied = batcher.insert(query); batcher.close(); // Commit and return dc.commit(); response.setDone("Copied " + spotsCopied + " spots."); } catch (Throwable t) { response.setError(t.getMessage(), Arrays.asList(t)); } finally { if (dc != null) dc.close(); } }
See Section 29.5, “Analysis and the Dynamic and Batch API:s” for more examples of using the analysis API.
This class is an abstract base class. It is a useful
class for most analysis plug-ins to inherit from. Its main
purpose is to define PluginParameter
The source bioassay set:
getSourceBioAssaySetParameter()
,
getCurrentBioAssaySet()
,
getSourceBioAssaySet()
The optional restriction of which bioassays to use.
All bioassays in a bioassay set will be used if this
parameter is empty. This is useful when the plugin only
should run on a subset of bioassays in a bioassay set:
getSourceBioAssaysParameter()
,
getSourceBioAssays()
The name and description of the child bioassay set that
is going to be created by the plug-in:
getChildNameParameter()
,
getChildDescriptionParameter()
The name and description of the transformation that
represents the execution of the plug-in:
getTransformationNameParameter()
,
getTransformationName()
The net.sf.basedb.core.plugin.AnalysisFilterPlugin
The interface exists purely for making the user interaction better. There is no harm in not implementing it since the plug-in will always appear in from the
button. On the other hand, it doesn't cost anything to implement the interface since it doesn't have any methods.