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()
should include: [Item.BIOASSAYSET
, Type.ITEM
]
or [Item.DERIVEDBIOASSAYSET
, Type.ITEM
]
since web client doesn't look for analysis plug-ins in most other places. 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. The following
code examples are taken from an analysis plug-in that is used in an experiment
context.
private static final Set<GuiContext> guiContexts = Collections.singleton(new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM)); public Set<GuiContext> getGuiContexts() { return guiContexts; }
If the plug-in 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 plug-in 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, “The Dynamic API” 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 used in an experiment context
to inherit from. Its main
purpose is to define PluginParameter
objects that are commonly used in analysis plug-ins. This includes:
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
is a tagging interface, with no methods, that all analysis plug-ins that only filters
data should implement. The benefit is that they will be linked from the
button and not just
the button. They will also get
a different icon in the experiment outline to make filtering
transformations appear different from other transformations.
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.