extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/MBafPlotterPlugin.java

Code
Comments
Other
Rev Date Author Line
5054 26 Oct 18 nicklas 1 package net.sf.basedb.reggie.plugins;
5054 26 Oct 18 nicklas 2
5054 26 Oct 18 nicklas 3 import java.io.IOException;
5054 26 Oct 18 nicklas 4 import java.io.InputStream;
5054 26 Oct 18 nicklas 5 import java.util.ArrayList;
5054 26 Oct 18 nicklas 6 import java.util.Arrays;
5054 26 Oct 18 nicklas 7 import java.util.Collections;
5054 26 Oct 18 nicklas 8 import java.util.HashSet;
5054 26 Oct 18 nicklas 9 import java.util.List;
5054 26 Oct 18 nicklas 10 import java.util.Set;
5054 26 Oct 18 nicklas 11
5054 26 Oct 18 nicklas 12 import net.sf.basedb.core.AnyToAny;
5054 26 Oct 18 nicklas 13 import net.sf.basedb.core.BaseException;
5054 26 Oct 18 nicklas 14 import net.sf.basedb.core.BooleanParameterType;
5054 26 Oct 18 nicklas 15 import net.sf.basedb.core.DbControl;
5054 26 Oct 18 nicklas 16 import net.sf.basedb.core.DerivedBioAssay;
5054 26 Oct 18 nicklas 17 import net.sf.basedb.core.Directory;
5054 26 Oct 18 nicklas 18 import net.sf.basedb.core.File;
5054 26 Oct 18 nicklas 19 import net.sf.basedb.core.FloatParameterType;
5054 26 Oct 18 nicklas 20 import net.sf.basedb.core.IntegerParameterType;
5054 26 Oct 18 nicklas 21 import net.sf.basedb.core.Item;
5054 26 Oct 18 nicklas 22 import net.sf.basedb.core.ItemContext;
5054 26 Oct 18 nicklas 23 import net.sf.basedb.core.ItemParameterType;
5054 26 Oct 18 nicklas 24 import net.sf.basedb.core.ItemQuery;
5054 26 Oct 18 nicklas 25 import net.sf.basedb.core.Path;
5054 26 Oct 18 nicklas 26 import net.sf.basedb.core.PluginDefinition;
5054 26 Oct 18 nicklas 27 import net.sf.basedb.core.PluginParameter;
5054 26 Oct 18 nicklas 28 import net.sf.basedb.core.ProgressReporter;
5054 26 Oct 18 nicklas 29 import net.sf.basedb.core.RequestInformation;
5057 29 Oct 18 nicklas 30 import net.sf.basedb.core.Software;
5054 26 Oct 18 nicklas 31 import net.sf.basedb.core.Type;
5054 26 Oct 18 nicklas 32 import net.sf.basedb.core.Job.ExecutionTime;
5054 26 Oct 18 nicklas 33 import net.sf.basedb.core.StringParameterType;
5054 26 Oct 18 nicklas 34 import net.sf.basedb.core.plugin.AbstractExporterPlugin;
5054 26 Oct 18 nicklas 35 import net.sf.basedb.core.plugin.ExportOutputStream;
5054 26 Oct 18 nicklas 36 import net.sf.basedb.core.plugin.GuiContext;
5054 26 Oct 18 nicklas 37 import net.sf.basedb.core.plugin.InteractivePlugin;
5054 26 Oct 18 nicklas 38 import net.sf.basedb.core.plugin.Request;
5054 26 Oct 18 nicklas 39 import net.sf.basedb.core.plugin.Response;
5054 26 Oct 18 nicklas 40 import net.sf.basedb.core.query.Expressions;
5054 26 Oct 18 nicklas 41 import net.sf.basedb.core.query.Hql;
5054 26 Oct 18 nicklas 42 import net.sf.basedb.core.query.Restrictions;
5054 26 Oct 18 nicklas 43 import net.sf.basedb.core.signal.SignalHandler;
5054 26 Oct 18 nicklas 44 import net.sf.basedb.core.signal.SignalTarget;
5054 26 Oct 18 nicklas 45 import net.sf.basedb.core.signal.ThreadSignalHandler;
5054 26 Oct 18 nicklas 46 import net.sf.basedb.reggie.Reggie;
5054 26 Oct 18 nicklas 47 import net.sf.basedb.reggie.baf.BafData;
5054 26 Oct 18 nicklas 48 import net.sf.basedb.reggie.baf.MBafOptions;
5054 26 Oct 18 nicklas 49 import net.sf.basedb.reggie.baf.MBafParser;
5054 26 Oct 18 nicklas 50 import net.sf.basedb.reggie.baf.MBafPlot;
5054 26 Oct 18 nicklas 51 import net.sf.basedb.reggie.dao.Annotationtype;
5054 26 Oct 18 nicklas 52 import net.sf.basedb.reggie.query.AnyToAnyRestriction;
6036 02 Nov 20 nicklas 53 import net.sf.basedb.reggie.script.ScriptResult;
5054 26 Oct 18 nicklas 54 import net.sf.basedb.util.Enumeration;
5054 26 Oct 18 nicklas 55 import net.sf.basedb.util.FileExportOutputStream;
5054 26 Oct 18 nicklas 56 import net.sf.basedb.util.FileUtil;
5054 26 Oct 18 nicklas 57
5054 26 Oct 18 nicklas 58 public class MBafPlotterPlugin 
5054 26 Oct 18 nicklas 59   extends AbstractExporterPlugin 
5054 26 Oct 18 nicklas 60   implements InteractivePlugin, SignalTarget  
5054 26 Oct 18 nicklas 61 {
5054 26 Oct 18 nicklas 62
5054 26 Oct 18 nicklas 63   
5054 26 Oct 18 nicklas 64   private ThreadSignalHandler signalHandler;
5054 26 Oct 18 nicklas 65   
5054 26 Oct 18 nicklas 66   public MBafPlotterPlugin()
5054 26 Oct 18 nicklas 67   {}
5054 26 Oct 18 nicklas 68   
5054 26 Oct 18 nicklas 69   /*
5054 26 Oct 18 nicklas 70      From the Plugin interface
5054 26 Oct 18 nicklas 71      --------------------------------
5054 26 Oct 18 nicklas 72   */
5054 26 Oct 18 nicklas 73   @Override
5054 26 Oct 18 nicklas 74   public boolean supportsConfigurations()
5054 26 Oct 18 nicklas 75   {
5054 26 Oct 18 nicklas 76     return false;
5054 26 Oct 18 nicklas 77   }
5054 26 Oct 18 nicklas 78   @Override
5054 26 Oct 18 nicklas 79   public boolean requiresConfiguration()
5054 26 Oct 18 nicklas 80   {
5054 26 Oct 18 nicklas 81     return false;
5054 26 Oct 18 nicklas 82   }
5054 26 Oct 18 nicklas 83
5054 26 Oct 18 nicklas 84   @Override
5054 26 Oct 18 nicklas 85   public void run(Request request, Response response, ProgressReporter progress)
5054 26 Oct 18 nicklas 86   {
5054 26 Oct 18 nicklas 87     if (signalHandler != null) signalHandler.setWorkerThread(null);
5054 26 Oct 18 nicklas 88     
5054 26 Oct 18 nicklas 89     if (job.getValue("alignment") != null)
5054 26 Oct 18 nicklas 90     {
5054 26 Oct 18 nicklas 91       // Single item context
5054 26 Oct 18 nicklas 92       super.run(request, response, progress);
5054 26 Oct 18 nicklas 93     }
5054 26 Oct 18 nicklas 94     else
5054 26 Oct 18 nicklas 95     {
5054 26 Oct 18 nicklas 96       DbControl dc = null;
5054 26 Oct 18 nicklas 97       try
5054 26 Oct 18 nicklas 98       {
5054 26 Oct 18 nicklas 99         dc = sc.newDbControl();
5054 26 Oct 18 nicklas 100         // List context or programmatic
5363 16 Apr 19 nicklas 101         List<DerivedBioAssay> alignments = job.getValues("alignments");      
5054 26 Oct 18 nicklas 102         
5057 29 Oct 18 nicklas 103         Software software = (Software)job.getValue("software");
5054 26 Oct 18 nicklas 104         String filename = (String)job.getValue("filename");
5054 26 Oct 18 nicklas 105         boolean overwrite = getOverwrite();
5054 26 Oct 18 nicklas 106         
5054 26 Oct 18 nicklas 107         begin(dc);
5054 26 Oct 18 nicklas 108         
5054 26 Oct 18 nicklas 109         int total = alignments.size();
5054 26 Oct 18 nicklas 110         int current = 0;
5054 26 Oct 18 nicklas 111         int skipped = 0;
5054 26 Oct 18 nicklas 112         int created = 0;
5054 26 Oct 18 nicklas 113         for (DerivedBioAssay alignment : alignments)
5054 26 Oct 18 nicklas 114         {
5054 26 Oct 18 nicklas 115           alignment = DerivedBioAssay.getById(dc, alignment.getId());
5054 26 Oct 18 nicklas 116           ThreadSignalHandler.checkInterrupted();
5054 26 Oct 18 nicklas 117
5054 26 Oct 18 nicklas 118           if (progress != null)
5054 26 Oct 18 nicklas 119           {
5054 26 Oct 18 nicklas 120             progress.display((100 * current) / total, "Creating mBAF plot for " + alignment.getName() + "...");
5054 26 Oct 18 nicklas 121           }
5054 26 Oct 18 nicklas 122           current++;
5054 26 Oct 18 nicklas 123           
5553 12 Aug 19 nicklas 124           boolean useExternalProjectArchive = Reggie.isExternalItem(alignment.getName());
5054 26 Oct 18 nicklas 125           String dataFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, alignment);
5054 26 Oct 18 nicklas 126           String baseFolder = (useExternalProjectArchive ? Reggie.EXTERNAL_ANALYSIS_DIR : Reggie.SECONDARY_ANALYSIS_DIR)
5054 26 Oct 18 nicklas 127               + Reggie.convertDataFilesFolderToBaseFolder(dataFolder);
5054 26 Oct 18 nicklas 128           Directory localDataDir = Directory.getNew(dc, new Path(baseFolder, Path.Type.DIRECTORY));
5054 26 Oct 18 nicklas 129
5054 26 Oct 18 nicklas 130           File saveTo = File.getFile(dc, localDataDir, filename, true);
5054 26 Oct 18 nicklas 131           if (saveTo.isInDatabase() && !saveTo.isRemoved() && !overwrite)
5054 26 Oct 18 nicklas 132           {
5054 26 Oct 18 nicklas 133             skipped++;
5054 26 Oct 18 nicklas 134             continue;
5054 26 Oct 18 nicklas 135           }
5054 26 Oct 18 nicklas 136           
5054 26 Oct 18 nicklas 137           created++;
5054 26 Oct 18 nicklas 138           if (!saveTo.isInDatabase()) dc.saveItem(saveTo);
5054 26 Oct 18 nicklas 139           
5057 29 Oct 18 nicklas 140           linkFileAndSoftware(dc, alignment, saveTo, software);
5054 26 Oct 18 nicklas 141
5054 26 Oct 18 nicklas 142           ExportOutputStream out = new FileExportOutputStream(saveTo, true);
5054 26 Oct 18 nicklas 143           performExport(alignment, out);
5054 26 Oct 18 nicklas 144         }
5054 26 Oct 18 nicklas 145         
5056 26 Oct 18 nicklas 146         if (progress != null) progress.display(95, "Created mBAF plots for " + created + " alignments. Saving to database...");
5054 26 Oct 18 nicklas 147         dc.commit();
5054 26 Oct 18 nicklas 148         end(true);
5054 26 Oct 18 nicklas 149         
5056 26 Oct 18 nicklas 150         String msg = "Created mBAF plots for " + created + " alignments.";
5054 26 Oct 18 nicklas 151         if (skipped > 0) msg += " Skipped " + skipped + " that already existed.";
5054 26 Oct 18 nicklas 152         response.setDone(msg);
5054 26 Oct 18 nicklas 153       }
5054 26 Oct 18 nicklas 154       catch (Throwable t)
5054 26 Oct 18 nicklas 155       {
5054 26 Oct 18 nicklas 156         end(false);
5054 26 Oct 18 nicklas 157         response.setError(t.getMessage(), Arrays.asList(new Throwable[] { t }));
5054 26 Oct 18 nicklas 158       }
5054 26 Oct 18 nicklas 159       finally
5054 26 Oct 18 nicklas 160       {
5054 26 Oct 18 nicklas 161         if (dc != null) dc.close();
5054 26 Oct 18 nicklas 162       }
5054 26 Oct 18 nicklas 163     }
5054 26 Oct 18 nicklas 164   }
5054 26 Oct 18 nicklas 165
5054 26 Oct 18 nicklas 166   // -------------------------------------
5054 26 Oct 18 nicklas 167   /*
5054 26 Oct 18 nicklas 168      From the InteractivePlugin interface
5054 26 Oct 18 nicklas 169      -------------------------------------------
5054 26 Oct 18 nicklas 170   */
5054 26 Oct 18 nicklas 171   /**
5054 26 Oct 18 nicklas 172     The plug-in will appear on the single-item and list page for raw bioassays.
5054 26 Oct 18 nicklas 173   */
5054 26 Oct 18 nicklas 174   @Override
5054 26 Oct 18 nicklas 175   public Set<GuiContext> getGuiContexts()
5054 26 Oct 18 nicklas 176   {
5054 26 Oct 18 nicklas 177     Set<GuiContext> ctx = new HashSet<GuiContext>();
5054 26 Oct 18 nicklas 178     ctx.add(GuiContext.item(Item.DERIVEDBIOASSAY));
5054 26 Oct 18 nicklas 179     ctx.add(GuiContext.list(Item.DERIVEDBIOASSAY));
5054 26 Oct 18 nicklas 180     return Collections.unmodifiableSet(ctx);
5054 26 Oct 18 nicklas 181   }
5054 26 Oct 18 nicklas 182   /**
5054 26 Oct 18 nicklas 183     We accept all alignments that has a link to a VCF file.
5054 26 Oct 18 nicklas 184   */
5054 26 Oct 18 nicklas 185   @Override
5054 26 Oct 18 nicklas 186   public String isInContext(GuiContext context, Object item)
5054 26 Oct 18 nicklas 187   {
5054 26 Oct 18 nicklas 188     String message = null;
5054 26 Oct 18 nicklas 189     if (context.getType() == GuiContext.Type.ITEM)
5054 26 Oct 18 nicklas 190     {
5054 26 Oct 18 nicklas 191       if (item == null)
5054 26 Oct 18 nicklas 192       {
5054 26 Oct 18 nicklas 193         message = "The object is null";
5054 26 Oct 18 nicklas 194       }
5054 26 Oct 18 nicklas 195       else if (!(item instanceof DerivedBioAssay))
5054 26 Oct 18 nicklas 196       {
5054 26 Oct 18 nicklas 197         message = "The object is not a derived bioassay: " + item;
5054 26 Oct 18 nicklas 198       }
5054 26 Oct 18 nicklas 199     }
5054 26 Oct 18 nicklas 200     return message;
5054 26 Oct 18 nicklas 201   }
5054 26 Oct 18 nicklas 202   
5054 26 Oct 18 nicklas 203   @Override
5054 26 Oct 18 nicklas 204   public RequestInformation getRequestInformation(GuiContext context, String command) 
5054 26 Oct 18 nicklas 205     throws BaseException
5054 26 Oct 18 nicklas 206   {
5054 26 Oct 18 nicklas 207     RequestInformation requestInformation = null;
5054 26 Oct 18 nicklas 208     if (Request.COMMAND_CONFIGURE_JOB.equals(command))
5054 26 Oct 18 nicklas 209     {
5054 26 Oct 18 nicklas 210       requestInformation = getConfigureJobParameters(context, null);
5054 26 Oct 18 nicklas 211     }
5054 26 Oct 18 nicklas 212     return requestInformation;
5054 26 Oct 18 nicklas 213   }
5054 26 Oct 18 nicklas 214   
5054 26 Oct 18 nicklas 215   @SuppressWarnings("unchecked")
5054 26 Oct 18 nicklas 216   @Override
5054 26 Oct 18 nicklas 217   public void configure(GuiContext context, Request request, Response response)
5054 26 Oct 18 nicklas 218   {
5054 26 Oct 18 nicklas 219     String command = request.getCommand();
5054 26 Oct 18 nicklas 220     DbControl dc = null;
5054 26 Oct 18 nicklas 221     try
5054 26 Oct 18 nicklas 222     {
5054 26 Oct 18 nicklas 223       if (command.equals(Request.COMMAND_CONFIGURE_JOB))
5054 26 Oct 18 nicklas 224       {
5054 26 Oct 18 nicklas 225         RequestInformation ri = getConfigureJobParameters(context, !request.isAllowedImmediateExecution());
5054 26 Oct 18 nicklas 226         List<Throwable> errors = validateRequestParameters(ri.getParameters(), request);
5054 26 Oct 18 nicklas 227         if (errors != null)
5054 26 Oct 18 nicklas 228         {
5054 26 Oct 18 nicklas 229           response.setError(errors.size() + " invalid parameters were found in the request",errors);
5054 26 Oct 18 nicklas 230           return;
5054 26 Oct 18 nicklas 231         }
5054 26 Oct 18 nicklas 232   
5054 26 Oct 18 nicklas 233         // options
5054 26 Oct 18 nicklas 234         storeValue(job, request, ri.getParameter("sourceVcf"));
5054 26 Oct 18 nicklas 235         storeValue(job, request, ri.getParameter("minDP"));
5054 26 Oct 18 nicklas 236         storeValue(job, request, ri.getParameter("maxMBaf"));
5054 26 Oct 18 nicklas 237         storeValue(job, request, ri.getParameter("minSnpCount"));
5054 26 Oct 18 nicklas 238         storeValue(job, request, ri.getParameter("pVal"));
5054 26 Oct 18 nicklas 239
5054 26 Oct 18 nicklas 240         //storeValue(job, request, ri.getParameter("software"));
5054 26 Oct 18 nicklas 241         storeValue(job, request, ri.getParameter("updateAnnotations"));
5054 26 Oct 18 nicklas 242         
5054 26 Oct 18 nicklas 243         
5054 26 Oct 18 nicklas 244         String sourceVcfName = (String)request.getParameterValue("sourceVcf");
5054 26 Oct 18 nicklas 245         
5054 26 Oct 18 nicklas 246         if (context.getType() == GuiContext.Type.ITEM)
5054 26 Oct 18 nicklas 247         {
5054 26 Oct 18 nicklas 248           storeValue(job, request, ri.getParameter("alignment"));
5054 26 Oct 18 nicklas 249           DerivedBioAssay alignment = (DerivedBioAssay)job.getValue("alignment");
5054 26 Oct 18 nicklas 250           dc = sc.newDbControl();
5054 26 Oct 18 nicklas 251           if (!AnyToAny.exists(dc, alignment, sourceVcfName))
5054 26 Oct 18 nicklas 252           {
5054 26 Oct 18 nicklas 253             response.setError("The alignment doesn't have a '" + sourceVcfName + "' file", null);
5054 26 Oct 18 nicklas 254             return;
5054 26 Oct 18 nicklas 255           }
5054 26 Oct 18 nicklas 256           
5054 26 Oct 18 nicklas 257           if (request.getParameterValue(SAVE_AS) == null)
5054 26 Oct 18 nicklas 258           {
5054 26 Oct 18 nicklas 259             if (!request.isAllowedImmediateExecution())
5054 26 Oct 18 nicklas 260             {
5054 26 Oct 18 nicklas 261               response.setError("Immediate download is not allowed. Please specify a filename.", null);
5054 26 Oct 18 nicklas 262               return;
5054 26 Oct 18 nicklas 263             }
5054 26 Oct 18 nicklas 264             response.setDownloadImmediately("Creating mBAF plot: " + 
5054 26 Oct 18 nicklas 265                 alignment.getName(), ExecutionTime.SHORTEST, true);
5054 26 Oct 18 nicklas 266           }
5054 26 Oct 18 nicklas 267           else
5054 26 Oct 18 nicklas 268           {
5054 26 Oct 18 nicklas 269             Object parameterValue = request.getParameterValue(OVERWRITE); 
5054 26 Oct 18 nicklas 270             boolean overwrite = parameterValue != null ? (Boolean)parameterValue : false;
5054 26 Oct 18 nicklas 271             if (!pathCanBeUsed((String)request.getParameterValue(ri.getParameter(SAVE_AS).getName()), overwrite))
5054 26 Oct 18 nicklas 272             {
5054 26 Oct 18 nicklas 273               response.setError("File exists: " + (String)request.getParameterValue(ri.getParameter(SAVE_AS).getName()), null);
5054 26 Oct 18 nicklas 274               return;
5054 26 Oct 18 nicklas 275             }
5054 26 Oct 18 nicklas 276             storeValue(job, request, ri.getParameter(SAVE_AS));
5054 26 Oct 18 nicklas 277             storeValue(job, request, ri.getParameter(OVERWRITE));
5054 26 Oct 18 nicklas 278             response.setSuggestedJobName("Create mBAF plot: " + alignment.getName());
5054 26 Oct 18 nicklas 279             response.setDone("The job configuration is complete", ExecutionTime.SHORTEST);
5054 26 Oct 18 nicklas 280           }
5054 26 Oct 18 nicklas 281         }
5054 26 Oct 18 nicklas 282         else
5054 26 Oct 18 nicklas 283         {
5054 26 Oct 18 nicklas 284           storeValue(job, request, ri.getParameter("whichItems"));
5054 26 Oct 18 nicklas 285           storeValue(job, request, ri.getParameter("filename"));
5054 26 Oct 18 nicklas 286           storeValue(job, request, ri.getParameter(OVERWRITE));
5054 26 Oct 18 nicklas 287           String whichItems = (String)request.getParameterValue("whichItems");
5054 26 Oct 18 nicklas 288           
5054 26 Oct 18 nicklas 289           ItemContext cc = sc.getCurrentContext(context.getItem(), context.getSubContext());
5054 26 Oct 18 nicklas 290           ItemQuery<DerivedBioAssay> query = (ItemQuery<DerivedBioAssay>)cc.getQuery();
5054 26 Oct 18 nicklas 291           query.restrict(AnyToAnyRestriction.exists(sourceVcfName, Item.FILE));
5054 26 Oct 18 nicklas 292           if ("all".equals(whichItems))
5054 26 Oct 18 nicklas 293           {
5054 26 Oct 18 nicklas 294             query.setFirstResult(0);
5054 26 Oct 18 nicklas 295             query.setMaxResults(0);
5054 26 Oct 18 nicklas 296           }
5054 26 Oct 18 nicklas 297           else if ("selected".equals(whichItems))
5054 26 Oct 18 nicklas 298           {
5054 26 Oct 18 nicklas 299             query.setFirstResult(0);
5054 26 Oct 18 nicklas 300             query.setMaxResults(0);
5054 26 Oct 18 nicklas 301             query.restrict(
5054 26 Oct 18 nicklas 302               Restrictions.in(
5054 26 Oct 18 nicklas 303                 Hql.property("id"),
5054 26 Oct 18 nicklas 304                 Expressions.parameter("_selected_", cc.getSelected(), Type.INT)
5054 26 Oct 18 nicklas 305               )
5054 26 Oct 18 nicklas 306             );
5054 26 Oct 18 nicklas 307           }
5054 26 Oct 18 nicklas 308           
5054 26 Oct 18 nicklas 309           dc = sc.newDbControl();
5054 26 Oct 18 nicklas 310           List<DerivedBioAssay> alignments = query.list(dc);
5054 26 Oct 18 nicklas 311           if (alignments.size() == 0)
5054 26 Oct 18 nicklas 312           {
5054 26 Oct 18 nicklas 313             response.setError("None of the specified alignments have a '" + sourceVcfName + "' file", null);
5054 26 Oct 18 nicklas 314             return;
5054 26 Oct 18 nicklas 315           }
5054 26 Oct 18 nicklas 316           else
5054 26 Oct 18 nicklas 317           {
5054 26 Oct 18 nicklas 318             job.setValues("alignments", new ItemParameterType<DerivedBioAssay>(DerivedBioAssay.class, null, true, 0, null), alignments);
5054 26 Oct 18 nicklas 319             
5054 26 Oct 18 nicklas 320             response.setSuggestedJobName("Create mBAF plot for " + alignments.size() + " alignments");
5054 26 Oct 18 nicklas 321             response.setDone("The job configuration is complete", ExecutionTime.SHORTEST);
5054 26 Oct 18 nicklas 322           }
5054 26 Oct 18 nicklas 323         }
5054 26 Oct 18 nicklas 324       }
5054 26 Oct 18 nicklas 325     }
5054 26 Oct 18 nicklas 326     catch(Throwable ex)
5054 26 Oct 18 nicklas 327     {
5054 26 Oct 18 nicklas 328       response.setError(ex.getMessage(), Arrays.asList(ex));
5054 26 Oct 18 nicklas 329     }
5054 26 Oct 18 nicklas 330     finally
5054 26 Oct 18 nicklas 331     {
5054 26 Oct 18 nicklas 332       if (dc != null) dc.close();
5054 26 Oct 18 nicklas 333     }
5054 26 Oct 18 nicklas 334   }
5054 26 Oct 18 nicklas 335   // ------------------------------------------------
5054 26 Oct 18 nicklas 336
5054 26 Oct 18 nicklas 337   private RequestInformation getConfigureJobParameters(GuiContext context, Boolean requireFile)
5054 26 Oct 18 nicklas 338   {
5054 26 Oct 18 nicklas 339
5054 26 Oct 18 nicklas 340     RequestInformation configureJob = null;
5054 26 Oct 18 nicklas 341     
5054 26 Oct 18 nicklas 342     List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>();
5054 26 Oct 18 nicklas 343     DbControl dc = null;
5054 26 Oct 18 nicklas 344     try
5054 26 Oct 18 nicklas 345     {
5054 26 Oct 18 nicklas 346       ItemContext cc = sc.getCurrentContext(context.getItem(), context.getSubContext());
5054 26 Oct 18 nicklas 347       dc = sc.newDbControl();
5054 26 Oct 18 nicklas 348       if (context.getType() == GuiContext.Type.ITEM)
5054 26 Oct 18 nicklas 349       {
5054 26 Oct 18 nicklas 350         DerivedBioAssay alignment = null;
5054 26 Oct 18 nicklas 351         String baseFolder = null;
5054 26 Oct 18 nicklas 352         int currentBioAssayId = cc.getId();
5054 26 Oct 18 nicklas 353         if (currentBioAssayId != 0)
5054 26 Oct 18 nicklas 354         {
5054 26 Oct 18 nicklas 355           alignment = DerivedBioAssay.getById(dc, currentBioAssayId);
5553 12 Aug 19 nicklas 356           boolean useExternalProjectArchive = Reggie.isExternalItem(alignment.getName());
5054 26 Oct 18 nicklas 357           String dataFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, alignment);
5054 26 Oct 18 nicklas 358           
5054 26 Oct 18 nicklas 359           baseFolder = (useExternalProjectArchive ? Reggie.EXTERNAL_ANALYSIS_DIR : Reggie.SECONDARY_ANALYSIS_DIR)
5054 26 Oct 18 nicklas 360               + Reggie.convertDataFilesFolderToBaseFolder(dataFolder);
5054 26 Oct 18 nicklas 361         }
5054 26 Oct 18 nicklas 362         if (requireFile == null)
5054 26 Oct 18 nicklas 363         {
5054 26 Oct 18 nicklas 364           PluginDefinition pd = job.getPluginDefinition();
5054 26 Oct 18 nicklas 365           requireFile = pd == null ? false : !pd.getAllowImmediateExecution();
5054 26 Oct 18 nicklas 366         }
5054 26 Oct 18 nicklas 367         String defaultPath = null;
5054 26 Oct 18 nicklas 368         if (requireFile && baseFolder != null)
5054 26 Oct 18 nicklas 369         {
5054 26 Oct 18 nicklas 370           defaultPath = baseFolder + Path.makeSafeFilename(alignment.getName(), "") + "-mbaf.png";
5054 26 Oct 18 nicklas 371         }
5054 26 Oct 18 nicklas 372         
5054 26 Oct 18 nicklas 373         parameters.add(new PluginParameter<DerivedBioAssay>(
5054 26 Oct 18 nicklas 374             "alignment", "Alignment", "Select the alignment to analyse.", 
5054 26 Oct 18 nicklas 375             new ItemParameterType<DerivedBioAssay>(DerivedBioAssay.class, alignment, true, 1, null)
5054 26 Oct 18 nicklas 376           ));
5054 26 Oct 18 nicklas 377         
5054 26 Oct 18 nicklas 378         parameters.addAll(getAnalysisParameters());
5054 26 Oct 18 nicklas 379         PluginParameter<String> saveAs = getSaveAsParameter(null, "The path to where the plot should be saved. Leave empty to download immediately." , defaultPath, requireFile);
5054 26 Oct 18 nicklas 380         parameters.addAll(getResultParameters(saveAs, null));
5054 26 Oct 18 nicklas 381         
5054 26 Oct 18 nicklas 382         configureJob = new RequestInformation
5054 26 Oct 18 nicklas 383         (
5054 26 Oct 18 nicklas 384           Request.COMMAND_CONFIGURE_JOB,
5054 26 Oct 18 nicklas 385           "Plot options",
5054 26 Oct 18 nicklas 386           "Select options for the mBAF calculations and what to do with the result.",
5054 26 Oct 18 nicklas 387           parameters
5054 26 Oct 18 nicklas 388         );
5054 26 Oct 18 nicklas 389       }
5054 26 Oct 18 nicklas 390       else
5054 26 Oct 18 nicklas 391       {
5054 26 Oct 18 nicklas 392         String defaultWhich = "all";
5054 26 Oct 18 nicklas 393         Enumeration<String, String> options = new Enumeration<String, String>();
5054 26 Oct 18 nicklas 394         if (cc.getSelected().size() > 0)
5054 26 Oct 18 nicklas 395         {
5054 26 Oct 18 nicklas 396           options.add("selected", "Selected items");
5054 26 Oct 18 nicklas 397           defaultWhich = "selected";
5054 26 Oct 18 nicklas 398         }
5054 26 Oct 18 nicklas 399         options.add("all", "All items");
5054 26 Oct 18 nicklas 400         
5054 26 Oct 18 nicklas 401         parameters.add(new PluginParameter<String>
5054 26 Oct 18 nicklas 402           (
5054 26 Oct 18 nicklas 403             "whichItems", "Which raw bioassays", "The raw bioassays to create a report for.", defaultWhich,
5054 26 Oct 18 nicklas 404             new StringParameterType(255, defaultWhich, true, 1, 0, 0, options)
5054 26 Oct 18 nicklas 405           ));
5054 26 Oct 18 nicklas 406         
5054 26 Oct 18 nicklas 407         parameters.addAll(getAnalysisParameters());
5054 26 Oct 18 nicklas 408         PluginParameter<String> saveTo = new PluginParameter<String>
5054 26 Oct 18 nicklas 409           (
5054 26 Oct 18 nicklas 410             "filename", "Filename", "Set filename for the plot.", "mbaf_genotype.png",
5054 26 Oct 18 nicklas 411             new StringParameterType(255, "mbaf_genotype.png", true)
5054 26 Oct 18 nicklas 412           );
5054 26 Oct 18 nicklas 413         parameters.addAll(getResultParameters(saveTo, true));
5054 26 Oct 18 nicklas 414         
5054 26 Oct 18 nicklas 415         configureJob = new RequestInformation
5054 26 Oct 18 nicklas 416         (
5054 26 Oct 18 nicklas 417           Request.COMMAND_CONFIGURE_JOB, 
5054 26 Oct 18 nicklas 418           "Plot options", 
5054 26 Oct 18 nicklas 419           "Select options for the mBAF calculations and what to do with the result.", 
5054 26 Oct 18 nicklas 420           parameters
5054 26 Oct 18 nicklas 421         );
5054 26 Oct 18 nicklas 422         dc.close();
5054 26 Oct 18 nicklas 423       }
5054 26 Oct 18 nicklas 424     }
5054 26 Oct 18 nicklas 425     finally
5054 26 Oct 18 nicklas 426     {
5054 26 Oct 18 nicklas 427       if (dc != null) dc.close();
5054 26 Oct 18 nicklas 428     }
5054 26 Oct 18 nicklas 429       
5054 26 Oct 18 nicklas 430     return configureJob;
5054 26 Oct 18 nicklas 431   }
5054 26 Oct 18 nicklas 432   /*
5054 26 Oct 18 nicklas 433     From the SignalTarget interface
5054 26 Oct 18 nicklas 434     -------------------------------------------
5054 26 Oct 18 nicklas 435   */
5054 26 Oct 18 nicklas 436   @Override
5054 26 Oct 18 nicklas 437   public SignalHandler getSignalHandler()
5054 26 Oct 18 nicklas 438   {
5054 26 Oct 18 nicklas 439     signalHandler = new ThreadSignalHandler();
5054 26 Oct 18 nicklas 440     return signalHandler;
5054 26 Oct 18 nicklas 441   }
5054 26 Oct 18 nicklas 442   // -------------------------------------------
5054 26 Oct 18 nicklas 443
5054 26 Oct 18 nicklas 444   /*
5054 26 Oct 18 nicklas 445     From the AbstractExporterPlugin interface
5054 26 Oct 18 nicklas 446     -----------------------------------------
5054 26 Oct 18 nicklas 447   */
5054 26 Oct 18 nicklas 448   private DbControl dc;
5054 26 Oct 18 nicklas 449   private MBafOptions options;
5054 26 Oct 18 nicklas 450   private MBafPlot plotter;
5054 26 Oct 18 nicklas 451   private MBafParser parser;
5054 26 Oct 18 nicklas 452   private String sourceVcf;
5054 26 Oct 18 nicklas 453   private boolean updateAnnotations;
5054 26 Oct 18 nicklas 454   
5054 26 Oct 18 nicklas 455   @Override
5054 26 Oct 18 nicklas 456   protected void begin(DbControl dc)
5054 26 Oct 18 nicklas 457   {
5054 26 Oct 18 nicklas 458     this.dc = dc;
5054 26 Oct 18 nicklas 459     this.options = new MBafOptions();
5054 26 Oct 18 nicklas 460     Integer minDP = (Integer)job.getValue("minDP");
5054 26 Oct 18 nicklas 461     if (minDP != null) options.setMinDP(minDP);
5054 26 Oct 18 nicklas 462     Float maxMBAF = (Float)job.getValue("maxMBaf");
5054 26 Oct 18 nicklas 463     if (maxMBAF != null) options.setMaxMBaf(maxMBAF);
5054 26 Oct 18 nicklas 464     Integer minSnpCount = (Integer)job.getValue("minSnpCount");
5054 26 Oct 18 nicklas 465     if (minSnpCount != null) options.setMinSnpCountForRegion(minSnpCount);
5054 26 Oct 18 nicklas 466     Float pVal = (Float)job.getValue("pVal");
5054 26 Oct 18 nicklas 467     if (pVal != null) options.setSignificantPVal(pVal);
5054 26 Oct 18 nicklas 468     this.sourceVcf = (String)job.getValue("sourceVcf");
5054 26 Oct 18 nicklas 469     this.updateAnnotations = Boolean.TRUE.equals(job.getValue("updateAnnotations"));
5054 26 Oct 18 nicklas 470     
5054 26 Oct 18 nicklas 471     this.plotter = new MBafPlot(options);
5054 26 Oct 18 nicklas 472     this.parser = new MBafParser();
5054 26 Oct 18 nicklas 473   }
5054 26 Oct 18 nicklas 474   
5054 26 Oct 18 nicklas 475   @Override
5054 26 Oct 18 nicklas 476   protected void performExport(ExportOutputStream out, ProgressReporter progress)
5054 26 Oct 18 nicklas 477     throws IOException
5054 26 Oct 18 nicklas 478   {
5054 26 Oct 18 nicklas 479     // This method is only called in the single-item case
5054 26 Oct 18 nicklas 480     try
5054 26 Oct 18 nicklas 481     {
5054 26 Oct 18 nicklas 482       DerivedBioAssay alignment = DerivedBioAssay.getById(dc, ((DerivedBioAssay)job.getValue("alignment")).getId());
5054 26 Oct 18 nicklas 483       performExport(alignment, out);
5054 26 Oct 18 nicklas 484       if (progress != null) progress.display(100, "mBAF plot generated succesfully");
5054 26 Oct 18 nicklas 485     }
5054 26 Oct 18 nicklas 486     catch (RuntimeException | IOException ex)
5054 26 Oct 18 nicklas 487     {
5054 26 Oct 18 nicklas 488       if (progress != null) progress.display(100, ex.getClass().getName() + ": " + ex.getMessage());
5054 26 Oct 18 nicklas 489       throw ex;
5054 26 Oct 18 nicklas 490     }
5054 26 Oct 18 nicklas 491   }
5054 26 Oct 18 nicklas 492   
5054 26 Oct 18 nicklas 493   @Override
5054 26 Oct 18 nicklas 494   protected void end(boolean success)
5054 26 Oct 18 nicklas 495   {
5056 26 Oct 18 nicklas 496     if (plotter != null) plotter.removeWorkDir();
5054 26 Oct 18 nicklas 497     this.dc = null;
5054 26 Oct 18 nicklas 498   }
5054 26 Oct 18 nicklas 499   
5054 26 Oct 18 nicklas 500   @Override
5054 26 Oct 18 nicklas 501   protected String getSuccessMessage()
5054 26 Oct 18 nicklas 502   {
5054 26 Oct 18 nicklas 503     return "mBAF plot generated successfully";
5054 26 Oct 18 nicklas 504   }
5054 26 Oct 18 nicklas 505   
5054 26 Oct 18 nicklas 506   private void performExport(DerivedBioAssay alignment, ExportOutputStream out)
5054 26 Oct 18 nicklas 507     throws IOException
5054 26 Oct 18 nicklas 508   {
5054 26 Oct 18 nicklas 509     // Save to png
5054 26 Oct 18 nicklas 510     out.setMimeType("image/png");
5054 26 Oct 18 nicklas 511     String filename = Path.makeSafeFilename(alignment.getName(), "")+"-mbaf.png";
5054 26 Oct 18 nicklas 512     out.setFilename(filename);
5054 26 Oct 18 nicklas 513     
6036 02 Nov 20 nicklas 514     ScriptResult result = null;
5054 26 Oct 18 nicklas 515     InputStream vcfIn = null;
5054 26 Oct 18 nicklas 516     try
5054 26 Oct 18 nicklas 517     {
5054 26 Oct 18 nicklas 518       AnyToAny link = AnyToAny.getByName(dc, alignment, sourceVcf);
5054 26 Oct 18 nicklas 519       File vcf = (File)link.getTo();
5054 26 Oct 18 nicklas 520       vcfIn = vcf.getDownloadStream(0);
5054 26 Oct 18 nicklas 521       
5054 26 Oct 18 nicklas 522       BafData bafData = parser.parse(vcfIn, vcf.getName());
5054 26 Oct 18 nicklas 523       if (bafData != null)
5054 26 Oct 18 nicklas 524       {
5054 26 Oct 18 nicklas 525         if (updateAnnotations)
5054 26 Oct 18 nicklas 526         {
5054 26 Oct 18 nicklas 527           bafData.collectMetrics().updateAnnotations(dc, alignment);
5054 26 Oct 18 nicklas 528         }
5054 26 Oct 18 nicklas 529         result = plotter.run(dc, alignment, bafData);
5054 26 Oct 18 nicklas 530         if (result.getExitStatus() != 0)
5054 26 Oct 18 nicklas 531         {
5054 26 Oct 18 nicklas 532           throw new RuntimeException(result.getStderr(), result.getException());
5054 26 Oct 18 nicklas 533         }
5054 26 Oct 18 nicklas 534         result.saveResultFile("mbafplot.png", out, false);
5054 26 Oct 18 nicklas 535       }
5054 26 Oct 18 nicklas 536     }
5054 26 Oct 18 nicklas 537     finally
5054 26 Oct 18 nicklas 538     {
5054 26 Oct 18 nicklas 539       FileUtil.close(vcfIn);
5054 26 Oct 18 nicklas 540     }
5054 26 Oct 18 nicklas 541   }
5054 26 Oct 18 nicklas 542   
5054 26 Oct 18 nicklas 543
5057 29 Oct 18 nicklas 544   private void linkFileAndSoftware(DbControl dc, DerivedBioAssay alignment, File file, Software software)
5054 26 Oct 18 nicklas 545   {
5064 31 Oct 18 nicklas 546     AnyToAny link = AnyToAny.getNewOrExisting(dc, alignment, file.getName(), file, false);
5054 26 Oct 18 nicklas 547     if (!link.isInDatabase()) dc.saveItem(link);
5057 29 Oct 18 nicklas 548     
5057 29 Oct 18 nicklas 549     if (software != null)
5057 29 Oct 18 nicklas 550     {
5057 29 Oct 18 nicklas 551       link.setDescription("Created with " + software.getName());
5064 31 Oct 18 nicklas 552       AnyToAny swLink = AnyToAny.getNewOrExisting(dc, file, "software", software, false);
5057 29 Oct 18 nicklas 553       if (!swLink.isInDatabase()) dc.saveItem(swLink);
5057 29 Oct 18 nicklas 554     }
5054 26 Oct 18 nicklas 555   }
5054 26 Oct 18 nicklas 556   
5054 26 Oct 18 nicklas 557   protected List<PluginParameter<?>> getAnalysisParameters()
5054 26 Oct 18 nicklas 558   {
5054 26 Oct 18 nicklas 559     List<PluginParameter<?>> parameters = new ArrayList<>();
5054 26 Oct 18 nicklas 560     parameters.add(new PluginParameter<String>(
5054 26 Oct 18 nicklas 561       "optionsSection", "mBAF analysis options", "Options affecting the mBAF analysis", null
5054 26 Oct 18 nicklas 562       ));
5054 26 Oct 18 nicklas 563
5054 26 Oct 18 nicklas 564     parameters.add(new PluginParameter<String>(
5054 26 Oct 18 nicklas 565       "sourceVcf", "Source VCF", "Name of the the linked VCF file that contains data for SNPs to be plotted.",
5054 26 Oct 18 nicklas 566       new StringParameterType(255, "mbaf_genotype.vcf", true)
5054 26 Oct 18 nicklas 567       ));
5054 26 Oct 18 nicklas 568     
5054 26 Oct 18 nicklas 569     parameters.add(new PluginParameter<Integer>(
5054 26 Oct 18 nicklas 570       "minDP", "Min reads/SNP", "Minimal number of reads that is required for a SNP to be used.",
5054 26 Oct 18 nicklas 571       new IntegerParameterType(10, null, MBafOptions.DEFAULT_MIN_DP, true)
5054 26 Oct 18 nicklas 572       ));
5054 26 Oct 18 nicklas 573     
5054 26 Oct 18 nicklas 574     parameters.add(new PluginParameter<Float>(
5054 26 Oct 18 nicklas 575       "maxMBaf", "Max mBAF", "SNPs with a higher mBAF value are not used since they are typically mixed with homzygous SNPs.",
5054 26 Oct 18 nicklas 576       new FloatParameterType(0.5f, 0.95f, MBafOptions.DEFAULT_MAX_MBAF, true)
5054 26 Oct 18 nicklas 577       ));
5054 26 Oct 18 nicklas 578     
5054 26 Oct 18 nicklas 579     parameters.add(new PluginParameter<Integer>(
5054 26 Oct 18 nicklas 580       "minSnpCount", "Min SNP count/region", "Regions must have at least this number of SNPs.",
5054 26 Oct 18 nicklas 581       new IntegerParameterType(10, null, MBafOptions.DEFAULT_MIN_SNPCOUNT_FOR_REGION, true)
5054 26 Oct 18 nicklas 582       ));
5054 26 Oct 18 nicklas 583     
5054 26 Oct 18 nicklas 584     parameters.add(new PluginParameter<Float>(
5054 26 Oct 18 nicklas 585       "pVal", "P-value", "Limit for p-value to be considered significant.",
5054 26 Oct 18 nicklas 586       new FloatParameterType(0f, 1f, MBafOptions.DEFAULT_SIGNIFICANT_PVAL, true)
5054 26 Oct 18 nicklas 587       ));
5054 26 Oct 18 nicklas 588     return parameters;
5054 26 Oct 18 nicklas 589   }
5054 26 Oct 18 nicklas 590   
5054 26 Oct 18 nicklas 591   protected List<PluginParameter<?>> getResultParameters(PluginParameter<String> saveAsParameter, Boolean updateAnnotationsDefault)
5054 26 Oct 18 nicklas 592   {
5054 26 Oct 18 nicklas 593     List<PluginParameter<?>> parameters = new ArrayList<>();
5054 26 Oct 18 nicklas 594     parameters.add(new PluginParameter<String>(
5054 26 Oct 18 nicklas 595       "results", "Results", "Options for the result.", null
5054 26 Oct 18 nicklas 596       ));
5054 26 Oct 18 nicklas 597     parameters.add(new PluginParameter<Boolean>("updateAnnotations", "Update annotations", 
5054 26 Oct 18 nicklas 598       "Save or update mBAF-related annotations on the alignment.", 
5054 26 Oct 18 nicklas 599       new BooleanParameterType(updateAnnotationsDefault, false)
5054 26 Oct 18 nicklas 600     ));
5054 26 Oct 18 nicklas 601     parameters.add(saveAsParameter);
5054 26 Oct 18 nicklas 602     parameters.add(getOverwriteParameter(null, null));
5054 26 Oct 18 nicklas 603
5054 26 Oct 18 nicklas 604     return parameters;
5054 26 Oct 18 nicklas 605   }
5054 26 Oct 18 nicklas 606 }