extensions/net.sf.basedb.examples/trunk/src/net/sf/basedb/examples/plugins/ExampleAnalyzer.java

Code
Comments
Other
Rev Date Author Line
647 11 Apr 08 nicklas 1 /*
1391 15 Sep 11 nicklas 2   Copyright (C) 2006, 2007, 2011 Nicklas Nordborg
647 11 Apr 08 nicklas 3
1391 15 Sep 11 nicklas 4   This file is part of the Example Code Package for BASE.
1391 15 Sep 11 nicklas 5   Available at http://baseplugins.thep.lu.se/
1391 15 Sep 11 nicklas 6   BASE main site: http://base.thep.lu.se/
1391 15 Sep 11 nicklas 7   
1391 15 Sep 11 nicklas 8   This is free software; you can redistribute it and/or
647 11 Apr 08 nicklas 9   modify it under the terms of the GNU General Public License
1391 15 Sep 11 nicklas 10   as published by the Free Software Foundation; either version 3
647 11 Apr 08 nicklas 11   of the License, or (at your option) any later version.
1391 15 Sep 11 nicklas 12   
1391 15 Sep 11 nicklas 13   The software is distributed in the hope that it will be useful,
647 11 Apr 08 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
647 11 Apr 08 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
647 11 Apr 08 nicklas 16   GNU General Public License for more details.
1391 15 Sep 11 nicklas 17   
647 11 Apr 08 nicklas 18   You should have received a copy of the GNU General Public License
1391 15 Sep 11 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
647 11 Apr 08 nicklas 20 */
1347 18 Apr 11 nicklas 21 package net.sf.basedb.examples.plugins;
647 11 Apr 08 nicklas 22
647 11 Apr 08 nicklas 23 import net.sf.basedb.core.BaseException;
647 11 Apr 08 nicklas 24 import net.sf.basedb.core.BioAssaySet;
647 11 Apr 08 nicklas 25 import net.sf.basedb.core.DbControl;
647 11 Apr 08 nicklas 26 import net.sf.basedb.core.DynamicSpotQuery;
647 11 Apr 08 nicklas 27 import net.sf.basedb.core.Item;
647 11 Apr 08 nicklas 28 import net.sf.basedb.core.Job;
647 11 Apr 08 nicklas 29 import net.sf.basedb.core.FloatParameterType;
647 11 Apr 08 nicklas 30 import net.sf.basedb.core.PluginParameter;
647 11 Apr 08 nicklas 31 import net.sf.basedb.core.ProgressReporter;
647 11 Apr 08 nicklas 32 import net.sf.basedb.core.RequestInformation;
647 11 Apr 08 nicklas 33 import net.sf.basedb.core.SpotBatcher;
647 11 Apr 08 nicklas 34 import net.sf.basedb.core.Transformation;
647 11 Apr 08 nicklas 35 import net.sf.basedb.core.VirtualColumn;
647 11 Apr 08 nicklas 36
647 11 Apr 08 nicklas 37 import net.sf.basedb.core.query.Dynamic;
647 11 Apr 08 nicklas 38 import net.sf.basedb.core.query.Expression;
647 11 Apr 08 nicklas 39 import net.sf.basedb.core.query.Expressions;
647 11 Apr 08 nicklas 40 import net.sf.basedb.core.query.Restrictions;
647 11 Apr 08 nicklas 41 import net.sf.basedb.core.query.Selects;
647 11 Apr 08 nicklas 42 import net.sf.basedb.core.signal.SignalHandler;
647 11 Apr 08 nicklas 43 import net.sf.basedb.core.signal.SignalTarget;
647 11 Apr 08 nicklas 44 import net.sf.basedb.core.signal.ThreadSignalHandler;
647 11 Apr 08 nicklas 45
1292 24 Feb 11 nicklas 46 import net.sf.basedb.core.plugin.AbstractAnalysisPlugin;
647 11 Apr 08 nicklas 47 import net.sf.basedb.core.plugin.InteractivePlugin;
647 11 Apr 08 nicklas 48 import net.sf.basedb.core.plugin.GuiContext;
647 11 Apr 08 nicklas 49 import net.sf.basedb.core.plugin.Request;
647 11 Apr 08 nicklas 50 import net.sf.basedb.core.plugin.Response;
647 11 Apr 08 nicklas 51
647 11 Apr 08 nicklas 52 import java.util.ArrayList;
647 11 Apr 08 nicklas 53 import java.util.Arrays;
647 11 Apr 08 nicklas 54 import java.util.Collections;
647 11 Apr 08 nicklas 55 import java.util.List;
647 11 Apr 08 nicklas 56 import java.util.Set;
647 11 Apr 08 nicklas 57
647 11 Apr 08 nicklas 58
647 11 Apr 08 nicklas 59 /**
647 11 Apr 08 nicklas 60   An example analysis plugin that creates a new bioassay set 
647 11 Apr 08 nicklas 61   by multiplying each intensitity value with the same factor, filtering
647 11 Apr 08 nicklas 62   out intensities below a cutoff value.
647 11 Apr 08 nicklas 63   
647 11 Apr 08 nicklas 64   @base.modified $Date$
647 11 Apr 08 nicklas 65   @author Nicklas
647 11 Apr 08 nicklas 66   @version 2.0
647 11 Apr 08 nicklas 67 */
647 11 Apr 08 nicklas 68 public class ExampleAnalyzer 
1292 24 Feb 11 nicklas 69   extends AbstractAnalysisPlugin
647 11 Apr 08 nicklas 70   implements InteractivePlugin, SignalTarget
647 11 Apr 08 nicklas 71 {
647 11 Apr 08 nicklas 72   private static final Set<GuiContext> guiContexts = Collections.singleton(
647 11 Apr 08 nicklas 73     new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM)
647 11 Apr 08 nicklas 74   );
647 11 Apr 08 nicklas 75   
647 11 Apr 08 nicklas 76   // Job configuration is created by getConfigureJob()
647 11 Apr 08 nicklas 77   private RequestInformation configureJob;
647 11 Apr 08 nicklas 78   
647 11 Apr 08 nicklas 79   // Intensities below this value will be filtered out
647 11 Apr 08 nicklas 80   private PluginParameter<Float> cutoffParameter;
647 11 Apr 08 nicklas 81   
647 11 Apr 08 nicklas 82   // Multiply each intensity with this value
647 11 Apr 08 nicklas 83   private PluginParameter<Float> factorParameter;
647 11 Apr 08 nicklas 84   
647 11 Apr 08 nicklas 85   // So we can react to ABORT requests
647 11 Apr 08 nicklas 86   private ThreadSignalHandler signalHandler;
647 11 Apr 08 nicklas 87   
647 11 Apr 08 nicklas 88   /**
647 11 Apr 08 nicklas 89     Create a new plugin instance.
647 11 Apr 08 nicklas 90   */
647 11 Apr 08 nicklas 91   public ExampleAnalyzer()
647 11 Apr 08 nicklas 92   {}
647 11 Apr 08 nicklas 93   
647 11 Apr 08 nicklas 94   /*
647 11 Apr 08 nicklas 95     From the Plugin interface
647 11 Apr 08 nicklas 96     -------------------------------------------
647 11 Apr 08 nicklas 97   */
1292 24 Feb 11 nicklas 98   @Override
647 11 Apr 08 nicklas 99   public boolean supportsConfigurations()
647 11 Apr 08 nicklas 100   {
647 11 Apr 08 nicklas 101     return false;
647 11 Apr 08 nicklas 102   }
1292 24 Feb 11 nicklas 103   @Override
647 11 Apr 08 nicklas 104   public boolean requiresConfiguration()
647 11 Apr 08 nicklas 105   {
647 11 Apr 08 nicklas 106     return false;
647 11 Apr 08 nicklas 107   }
1292 24 Feb 11 nicklas 108   @Override
647 11 Apr 08 nicklas 109   public void run(Request request, Response response, ProgressReporter progress)
647 11 Apr 08 nicklas 110   {
647 11 Apr 08 nicklas 111     // Ensure that the ABORT signal gets sent to this thread
647 11 Apr 08 nicklas 112     if (signalHandler != null) signalHandler.setWorkerThread(null);
647 11 Apr 08 nicklas 113
647 11 Apr 08 nicklas 114     // Open a connection to the database
647 11 Apr 08 nicklas 115     // sc is set by init() method
647 11 Apr 08 nicklas 116     DbControl dc = sc.newDbControl();
647 11 Apr 08 nicklas 117     try
647 11 Apr 08 nicklas 118     {
647 11 Apr 08 nicklas 119       // Get job parameters
647 11 Apr 08 nicklas 120       float cutoff = (Float)job.getValue("cutoff");
647 11 Apr 08 nicklas 121       float factor = (Float)job.getValue("factor");
1292 24 Feb 11 nicklas 122       BioAssaySet source = getSourceBioAssaySet(dc);
647 11 Apr 08 nicklas 123       int channels = source.getRawDataType().getChannels();
647 11 Apr 08 nicklas 124         
647 11 Apr 08 nicklas 125       // Create transformation and child bioassay set
647 11 Apr 08 nicklas 126       Job j = Job.getById(dc, job.getId());
647 11 Apr 08 nicklas 127       Transformation t = source.newTransformation(j);
647 11 Apr 08 nicklas 128       t.setName("Multiply " + factor + "; filter < " + cutoff);
647 11 Apr 08 nicklas 129       BioAssaySet result = t.newProduct(null, "new", true);
647 11 Apr 08 nicklas 130       result.setName("After: multiply and filter");
647 11 Apr 08 nicklas 131       dc.saveItem(t);
647 11 Apr 08 nicklas 132       dc.saveItem(result);
647 11 Apr 08 nicklas 133         
647 11 Apr 08 nicklas 134       // Get query for source data
647 11 Apr 08 nicklas 135       DynamicSpotQuery query = source.getSpotData();
647 11 Apr 08 nicklas 136         
647 11 Apr 08 nicklas 137       // Query expressions for multiplication factor and cutoff
647 11 Apr 08 nicklas 138       Expression factorExpression = Expressions.aFloat(factor);
647 11 Apr 08 nicklas 139       Expression cutoffExpression = Expressions.aFloat(cutoff);
647 11 Apr 08 nicklas 140               
647 11 Apr 08 nicklas 141       // Specify select columns
647 11 Apr 08 nicklas 142       query.select(Dynamic.select(VirtualColumn.COLUMN));
647 11 Apr 08 nicklas 143       query.select(Dynamic.select(VirtualColumn.POSITION));
647 11 Apr 08 nicklas 144       for (int ch = 1; ch <= channels; ch++)
647 11 Apr 08 nicklas 145       {
1292 24 Feb 11 nicklas 146         Expression chExpression = Dynamic.column(VirtualColumn.channelRaw(ch));
647 11 Apr 08 nicklas 147         // Selects: ch * factor for each channel
647 11 Apr 08 nicklas 148         query.select(
647 11 Apr 08 nicklas 149           Selects.expression(Expressions.multiply(chExpression, factorExpression), "ch" + ch)
647 11 Apr 08 nicklas 150         );
647 11 Apr 08 nicklas 151         // Restricts: ch >= cutoff for each channel
647 11 Apr 08 nicklas 152         query.restrict(Restrictions.gteq(chExpression, cutoffExpression));
647 11 Apr 08 nicklas 153       }
647 11 Apr 08 nicklas 154         
647 11 Apr 08 nicklas 155       // Create batcher and copy data
647 11 Apr 08 nicklas 156       SpotBatcher batcher = result.getSpotBatcher();
647 11 Apr 08 nicklas 157       // Check for the ABORT signal before a lengthy operation
1292 24 Feb 11 nicklas 158       ThreadSignalHandler.checkInterrupted(); 
647 11 Apr 08 nicklas 159       int spotsCopied = batcher.insert(query);
647 11 Apr 08 nicklas 160       batcher.close();
647 11 Apr 08 nicklas 161       int spotsRemoved = source.getNumSpots() - spotsCopied;
647 11 Apr 08 nicklas 162         
647 11 Apr 08 nicklas 163       // Commit the work
647 11 Apr 08 nicklas 164       dc.commit();
647 11 Apr 08 nicklas 165       response.setDone("Multiplied " + spotsCopied + " spots with factor " + factor + 
647 11 Apr 08 nicklas 166         "; removed " + spotsRemoved + " spots with intensity < " + cutoff);
647 11 Apr 08 nicklas 167     }
647 11 Apr 08 nicklas 168     catch (Throwable t)
647 11 Apr 08 nicklas 169     {
647 11 Apr 08 nicklas 170       // All exceptions must be catched and sent back 
647 11 Apr 08 nicklas 171       // using the response object
647 11 Apr 08 nicklas 172       response.setError(t.getMessage(), Arrays.asList(t));
647 11 Apr 08 nicklas 173     }
647 11 Apr 08 nicklas 174     finally
647 11 Apr 08 nicklas 175     {
647 11 Apr 08 nicklas 176       // IMPORTANT!!! Make sure opened connections are closed
647 11 Apr 08 nicklas 177       if (dc != null) dc.close();
647 11 Apr 08 nicklas 178     }
647 11 Apr 08 nicklas 179   }
647 11 Apr 08 nicklas 180   // -------------------------------------------
647 11 Apr 08 nicklas 181   
647 11 Apr 08 nicklas 182   /*
647 11 Apr 08 nicklas 183     From the InteractivePlugin interface
647 11 Apr 08 nicklas 184     -------------------------------------------
647 11 Apr 08 nicklas 185   */
647 11 Apr 08 nicklas 186   /**
647 11 Apr 08 nicklas 187     Return a set containing the context [BIOASSAYSET, ITEM].
647 11 Apr 08 nicklas 188   */
1292 24 Feb 11 nicklas 189   @Override
647 11 Apr 08 nicklas 190   public Set<GuiContext> getGuiContexts()
647 11 Apr 08 nicklas 191   {
647 11 Apr 08 nicklas 192     return guiContexts;
647 11 Apr 08 nicklas 193   }
647 11 Apr 08 nicklas 194   /**
647 11 Apr 08 nicklas 195     Check if the item is a {@link BioAssaySet} and the logged in
1292 24 Feb 11 nicklas 196     user has USE permission to the experiment. Also verify that
1292 24 Feb 11 nicklas 197     the bioassay set has data stored in the database.
647 11 Apr 08 nicklas 198   */
1292 24 Feb 11 nicklas 199   @Override
647 11 Apr 08 nicklas 200   public String isInContext(GuiContext context, Object item)
647 11 Apr 08 nicklas 201   {
1292 24 Feb 11 nicklas 202     String message = super.isInContext(context, item);
1292 24 Feb 11 nicklas 203     if (message == null)
647 11 Apr 08 nicklas 204     {
1292 24 Feb 11 nicklas 205       BioAssaySet bas = (BioAssaySet)item;
1292 24 Feb 11 nicklas 206       if (bas.getNumSpots() <= 0)
1292 24 Feb 11 nicklas 207       {
1292 24 Feb 11 nicklas 208         message = "This plug-in requires spot data in the database";
1292 24 Feb 11 nicklas 209       }
647 11 Apr 08 nicklas 210     }
647 11 Apr 08 nicklas 211     return message;
647 11 Apr 08 nicklas 212   }
647 11 Apr 08 nicklas 213   /**
647 11 Apr 08 nicklas 214     The {@link Request#COMMAND_CONFIGURE_PLUGIN} command will not ask
647 11 Apr 08 nicklas 215     for any parameters.
647 11 Apr 08 nicklas 216     <p>
647 11 Apr 08 nicklas 217     The {@link Request#COMMAND_CONFIGURE_JOB} command will ask for
647 11 Apr 08 nicklas 218     a bioassay set, a multiplcation factor and a cutoff value.
647 11 Apr 08 nicklas 219   */
1292 24 Feb 11 nicklas 220   @Override
647 11 Apr 08 nicklas 221   public RequestInformation getRequestInformation(GuiContext context, String command)
647 11 Apr 08 nicklas 222     throws BaseException
647 11 Apr 08 nicklas 223   {
647 11 Apr 08 nicklas 224     RequestInformation requestInformation = null;
647 11 Apr 08 nicklas 225     if (command.equals(Request.COMMAND_CONFIGURE_JOB))
647 11 Apr 08 nicklas 226     {
647 11 Apr 08 nicklas 227       requestInformation = getConfigureJob(context);
647 11 Apr 08 nicklas 228     }
647 11 Apr 08 nicklas 229     return requestInformation;
647 11 Apr 08 nicklas 230   }
647 11 Apr 08 nicklas 231   /**
647 11 Apr 08 nicklas 232     Store configuration settings for {@link Request#COMMAND_CONFIGURE_PLUGIN} and
647 11 Apr 08 nicklas 233     {@link Request#COMMAND_CONFIGURE_JOB}.
647 11 Apr 08 nicklas 234   */
1292 24 Feb 11 nicklas 235   @Override
647 11 Apr 08 nicklas 236   public void configure(GuiContext context, Request request, Response response)
647 11 Apr 08 nicklas 237   {
647 11 Apr 08 nicklas 238     String command = request.getCommand();
647 11 Apr 08 nicklas 239     try
647 11 Apr 08 nicklas 240     {
647 11 Apr 08 nicklas 241       if (command.equals(Request.COMMAND_CONFIGURE_JOB))
647 11 Apr 08 nicklas 242       {
1292 24 Feb 11 nicklas 243         RequestInformation ri = getConfigureJob(context);
647 11 Apr 08 nicklas 244         List<Throwable> errors = 
1292 24 Feb 11 nicklas 245           validateRequestParameters(ri.getParameters(), request);
647 11 Apr 08 nicklas 246         if (errors != null)
647 11 Apr 08 nicklas 247         {
647 11 Apr 08 nicklas 248           response.setError(errors.size()+" invalid parameter(s) were found in the request", errors);
647 11 Apr 08 nicklas 249           return;
647 11 Apr 08 nicklas 250         }
647 11 Apr 08 nicklas 251
1292 24 Feb 11 nicklas 252         // Source bioassay set
1292 24 Feb 11 nicklas 253         storeValue(job, request, ri.getParameter(SOURCE_BIOASSAYSET));
1292 24 Feb 11 nicklas 254                 
1292 24 Feb 11 nicklas 255         // Other options
647 11 Apr 08 nicklas 256         storeValue(job, request, factorParameter);
647 11 Apr 08 nicklas 257         storeValue(job, request, cutoffParameter);
1292 24 Feb 11 nicklas 258         BioAssaySet bioAssaySet = (BioAssaySet)job.getValue(SOURCE_BIOASSAYSET);
1292 24 Feb 11 nicklas 259         response.setSuggestedJobName("Example analysis on bioassay set '" + 
1292 24 Feb 11 nicklas 260             bioAssaySet.getName() + "'");
647 11 Apr 08 nicklas 261         response.setDone("Job configuration complete", Job.ExecutionTime.SHORT);
647 11 Apr 08 nicklas 262         // TODO - maybe check file size to make a better estimate
647 11 Apr 08 nicklas 263       }
647 11 Apr 08 nicklas 264     }
647 11 Apr 08 nicklas 265     catch (Throwable ex)
647 11 Apr 08 nicklas 266     {
647 11 Apr 08 nicklas 267       response.setError(ex.getMessage(), Arrays.asList(ex));
647 11 Apr 08 nicklas 268     }
647 11 Apr 08 nicklas 269   }
647 11 Apr 08 nicklas 270   // -------------------------------------------
647 11 Apr 08 nicklas 271   /*
647 11 Apr 08 nicklas 272     From the SignalTarget interface
647 11 Apr 08 nicklas 273     -------------------------------------------
647 11 Apr 08 nicklas 274   */
1292 24 Feb 11 nicklas 275   @Override
647 11 Apr 08 nicklas 276   public SignalHandler getSignalHandler()
647 11 Apr 08 nicklas 277   {
647 11 Apr 08 nicklas 278     signalHandler = new ThreadSignalHandler();
647 11 Apr 08 nicklas 279     return signalHandler;
647 11 Apr 08 nicklas 280   }
647 11 Apr 08 nicklas 281   // -------------------------------------------
647 11 Apr 08 nicklas 282
647 11 Apr 08 nicklas 283
647 11 Apr 08 nicklas 284   private RequestInformation getConfigureJob(GuiContext context)
647 11 Apr 08 nicklas 285   {
1292 24 Feb 11 nicklas 286     DbControl dc = null;
1292 24 Feb 11 nicklas 287     try
647 11 Apr 08 nicklas 288     {
1292 24 Feb 11 nicklas 289       if (configureJob == null)
1292 24 Feb 11 nicklas 290       {
1292 24 Feb 11 nicklas 291         dc = sc.newDbControl();
1292 24 Feb 11 nicklas 292         BioAssaySet bas = getCurrentBioAssaySet(dc);
1292 24 Feb 11 nicklas 293         // Create parameter list and request informaion
1292 24 Feb 11 nicklas 294         List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>();
1292 24 Feb 11 nicklas 295         
1292 24 Feb 11 nicklas 296         // Source bioassay set parameter
1292 24 Feb 11 nicklas 297         parameters.add(getSourceBioAssaySetParameter(null, null));    
1292 24 Feb 11 nicklas 298   
1292 24 Feb 11 nicklas 299         // Other parameters
1292 24 Feb 11 nicklas 300         // Create multiplication factor parameter
1292 24 Feb 11 nicklas 301         factorParameter = new PluginParameter<Float>(
1292 24 Feb 11 nicklas 302           "factor",
1292 24 Feb 11 nicklas 303           "Multiplication factor",
1292 24 Feb 11 nicklas 304           "The factor to multiply each spot intensity with.",
1292 24 Feb 11 nicklas 305           new FloatParameterType(0.0f, 100.0f, 1.0f, true)
1292 24 Feb 11 nicklas 306         );
1292 24 Feb 11 nicklas 307   
1292 24 Feb 11 nicklas 308         // Create cutoff parameter
1292 24 Feb 11 nicklas 309         cutoffParameter = new PluginParameter<Float>(
1292 24 Feb 11 nicklas 310           "cutoff",
1292 24 Feb 11 nicklas 311           "Cut-off value",
1292 24 Feb 11 nicklas 312           "Original intensities falling below this value are filtered out.",
1292 24 Feb 11 nicklas 313           new FloatParameterType(null, null, 0.0f, true)
1292 24 Feb 11 nicklas 314         );
1292 24 Feb 11 nicklas 315         parameters.add(factorParameter);
1292 24 Feb 11 nicklas 316         parameters.add(cutoffParameter);
1292 24 Feb 11 nicklas 317         
1292 24 Feb 11 nicklas 318         configureJob = new RequestInformation
1292 24 Feb 11 nicklas 319         (
1292 24 Feb 11 nicklas 320           Request.COMMAND_CONFIGURE_JOB,
1292 24 Feb 11 nicklas 321           "Specify multiplication factor and cutoff",
1347 18 Apr 11 nicklas 322           "An example analysis plugin that creates a new bioassay set " + 
1347 18 Apr 11 nicklas 323           "by multiplying each intensitity value with the same factor, " +
1347 18 Apr 11 nicklas 324           "filtering out intensities below a cutoff value.",
1292 24 Feb 11 nicklas 325           parameters
1292 24 Feb 11 nicklas 326         );
1292 24 Feb 11 nicklas 327       }
647 11 Apr 08 nicklas 328     }
1292 24 Feb 11 nicklas 329     finally
1292 24 Feb 11 nicklas 330     {
1292 24 Feb 11 nicklas 331       if (dc != null) dc.close();
1292 24 Feb 11 nicklas 332     }
647 11 Apr 08 nicklas 333     return configureJob;
647 11 Apr 08 nicklas 334   }
647 11 Apr 08 nicklas 335 }