extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/grid/StringTie2023JobCreator.java

Code
Comments
Other
Rev Date Author Line
6821 29 Aug 22 nicklas 1 package net.sf.basedb.reggie.grid;
6821 29 Aug 22 nicklas 2
6821 29 Aug 22 nicklas 3 import java.io.IOException;
6821 29 Aug 22 nicklas 4 import java.io.InputStream;
6821 29 Aug 22 nicklas 5 import java.util.ArrayList;
6821 29 Aug 22 nicklas 6 import java.util.HashSet;
6821 29 Aug 22 nicklas 7 import java.util.List;
6821 29 Aug 22 nicklas 8 import java.util.Set;
6821 29 Aug 22 nicklas 9 import java.util.regex.Matcher;
6821 29 Aug 22 nicklas 10 import java.util.regex.Pattern;
6821 29 Aug 22 nicklas 11
6821 29 Aug 22 nicklas 12 import org.slf4j.LoggerFactory;
6821 29 Aug 22 nicklas 13
6821 29 Aug 22 nicklas 14 import net.sf.basedb.core.AnyToAny;
6821 29 Aug 22 nicklas 15 import net.sf.basedb.core.ArrayDesign;
6821 29 Aug 22 nicklas 16 import net.sf.basedb.core.DataFileType;
6821 29 Aug 22 nicklas 17 import net.sf.basedb.core.DbControl;
6821 29 Aug 22 nicklas 18 import net.sf.basedb.core.DerivedBioAssay;
6821 29 Aug 22 nicklas 19 import net.sf.basedb.core.Directory;
6821 29 Aug 22 nicklas 20 import net.sf.basedb.core.File;
6821 29 Aug 22 nicklas 21 import net.sf.basedb.core.FileServer;
6821 29 Aug 22 nicklas 22 import net.sf.basedb.core.FileSetMember;
6821 29 Aug 22 nicklas 23 import net.sf.basedb.core.ItemList;
6821 29 Aug 22 nicklas 24 import net.sf.basedb.core.ItemNotFoundException;
6821 29 Aug 22 nicklas 25 import net.sf.basedb.core.ItemSubtype;
6821 29 Aug 22 nicklas 26 import net.sf.basedb.core.Job;
6821 29 Aug 22 nicklas 27 import net.sf.basedb.core.Path;
6821 29 Aug 22 nicklas 28 import net.sf.basedb.core.Protocol;
6821 29 Aug 22 nicklas 29 import net.sf.basedb.core.RawBioAssay;
6821 29 Aug 22 nicklas 30 import net.sf.basedb.core.Sample;
6821 29 Aug 22 nicklas 31 import net.sf.basedb.core.SessionControl;
6821 29 Aug 22 nicklas 32 import net.sf.basedb.core.Software;
6821 29 Aug 22 nicklas 33 import net.sf.basedb.core.StringParameterType;
6821 29 Aug 22 nicklas 34 import net.sf.basedb.opengrid.JobDefinition;
6821 29 Aug 22 nicklas 35 import net.sf.basedb.opengrid.JobStatus;
6821 29 Aug 22 nicklas 36 import net.sf.basedb.opengrid.OpenGridCluster;
6821 29 Aug 22 nicklas 37 import net.sf.basedb.opengrid.OpenGridSession;
6821 29 Aug 22 nicklas 38 import net.sf.basedb.opengrid.ScriptBuilder;
6821 29 Aug 22 nicklas 39 import net.sf.basedb.opengrid.config.ClusterConfig;
6821 29 Aug 22 nicklas 40 import net.sf.basedb.opengrid.config.JobConfig;
6821 29 Aug 22 nicklas 41 import net.sf.basedb.opengrid.service.JobCompletionHandler;
6821 29 Aug 22 nicklas 42 import net.sf.basedb.reggie.Reggie;
6821 29 Aug 22 nicklas 43 import net.sf.basedb.reggie.XmlConfig;
6821 29 Aug 22 nicklas 44 import net.sf.basedb.reggie.dao.AlignedSequences;
6821 29 Aug 22 nicklas 45 import net.sf.basedb.reggie.dao.Annotationtype;
6821 29 Aug 22 nicklas 46 import net.sf.basedb.reggie.dao.BiomaterialList;
6821 29 Aug 22 nicklas 47 import net.sf.basedb.reggie.dao.Datafiletype;
6821 29 Aug 22 nicklas 48 import net.sf.basedb.reggie.dao.DemuxedSequences;
6821 29 Aug 22 nicklas 49 import net.sf.basedb.reggie.dao.DoNotUse;
6821 29 Aug 22 nicklas 50 import net.sf.basedb.reggie.dao.Fileserver;
6821 29 Aug 22 nicklas 51 import net.sf.basedb.reggie.dao.Library;
6821 29 Aug 22 nicklas 52 import net.sf.basedb.reggie.dao.MaskedSequences;
6821 29 Aug 22 nicklas 53 import net.sf.basedb.reggie.dao.MergedSequences;
6821 29 Aug 22 nicklas 54 import net.sf.basedb.reggie.dao.Pipeline;
6821 29 Aug 22 nicklas 55 import net.sf.basedb.reggie.dao.Rawbioassay;
6821 29 Aug 22 nicklas 56 import net.sf.basedb.reggie.dao.Rawdatatype;
6821 29 Aug 22 nicklas 57 import net.sf.basedb.reggie.dao.Subtype;
6821 29 Aug 22 nicklas 58 import net.sf.basedb.util.FileUtil;
6821 29 Aug 22 nicklas 59 import net.sf.basedb.util.Values;
7079 27 Mar 23 nicklas 60 import net.sf.basedb.util.extensions.logging.ExtensionsLog;
7079 27 Mar 23 nicklas 61 import net.sf.basedb.util.extensions.logging.ExtensionsLogger;
6821 29 Aug 22 nicklas 62 import net.sf.basedb.util.parser.FlatFileParser;
6821 29 Aug 22 nicklas 63 import net.sf.basedb.util.parser.FlatFileParser.LineType;
6821 29 Aug 22 nicklas 64
6821 29 Aug 22 nicklas 65 /**
6821 29 Aug 22 nicklas 66   Helper class for creating items needed for executing StringTie/2023 as
6821 29 Aug 22 nicklas 67   well as generating the StringTie script and send it to the cluster for
6821 29 Aug 22 nicklas 68   execution.
6821 29 Aug 22 nicklas 69   
6821 29 Aug 22 nicklas 70   @author nicklas
6821 29 Aug 22 nicklas 71   @since 4.40
6821 29 Aug 22 nicklas 72 */
6821 29 Aug 22 nicklas 73 public class StringTie2023JobCreator 
6821 29 Aug 22 nicklas 74   extends AbstractJobCreator
6821 29 Aug 22 nicklas 75 {
6821 29 Aug 22 nicklas 76   /**
6821 29 Aug 22 nicklas 77     Sum all parts of the read string that generate
6821 29 Aug 22 nicklas 78     an ouput read (eg. all T)
6821 29 Aug 22 nicklas 79   */
6821 29 Aug 22 nicklas 80   public static int getTotalReadSize(String readString)
6821 29 Aug 22 nicklas 81   {
6821 29 Aug 22 nicklas 82     Pattern p = Pattern.compile("(\\d+)T");
6821 29 Aug 22 nicklas 83     Matcher m = p.matcher(readString);
6821 29 Aug 22 nicklas 84     int totalReadSize = 0;
6821 29 Aug 22 nicklas 85     while (m.find())
6821 29 Aug 22 nicklas 86     {
6821 29 Aug 22 nicklas 87       totalReadSize += Values.getInt(m.group(1));
6821 29 Aug 22 nicklas 88     }
6821 29 Aug 22 nicklas 89     return totalReadSize;
6821 29 Aug 22 nicklas 90   }
6821 29 Aug 22 nicklas 91   
6821 29 Aug 22 nicklas 92   /**
6821 29 Aug 22 nicklas 93     Helper method for getting the read string from all demuxed sequences and
6821 29 Aug 22 nicklas 94     calculating the average length.
6821 29 Aug 22 nicklas 95   */
6821 29 Aug 22 nicklas 96   public static int getAverageReadSize(DbControl dc, AlignedSequences aligned)
6821 29 Aug 22 nicklas 97   {
6821 29 Aug 22 nicklas 98     MaskedSequences masked = aligned.getMaskedSequences(dc);
6821 29 Aug 22 nicklas 99     MergedSequences merged = masked.getMergedSequences(dc);
6821 29 Aug 22 nicklas 100     List<DemuxedSequences> dxList = merged.getDemuxedSequences(dc);
6821 29 Aug 22 nicklas 101     
6821 29 Aug 22 nicklas 102     int totalReadSize = 0;
6821 29 Aug 22 nicklas 103     for (DemuxedSequences dx : dxList)
6821 29 Aug 22 nicklas 104     {
6821 29 Aug 22 nicklas 105       String readString = (String)Annotationtype.READ_STRING.getAnnotationValue(dc, dx.getItem());
6821 29 Aug 22 nicklas 106       totalReadSize += getTotalReadSize(readString);
6821 29 Aug 22 nicklas 107     }
6821 29 Aug 22 nicklas 108     
6821 29 Aug 22 nicklas 109     return totalReadSize / dxList.size();
6821 29 Aug 22 nicklas 110   }
6821 29 Aug 22 nicklas 111   
6821 29 Aug 22 nicklas 112
6821 29 Aug 22 nicklas 113   private Software software;
6821 29 Aug 22 nicklas 114   private Protocol protocol;
6821 29 Aug 22 nicklas 115   private ArrayDesign arrayDesign;
6821 29 Aug 22 nicklas 116   
6821 29 Aug 22 nicklas 117   public StringTie2023JobCreator()
6821 29 Aug 22 nicklas 118   {}
6821 29 Aug 22 nicklas 119
6821 29 Aug 22 nicklas 120   /**
6821 29 Aug 22 nicklas 121     Set the software item to set on created RawBioAssay:s.
6821 29 Aug 22 nicklas 122     @see RawBioAssay#setSoftware(Software)
6821 29 Aug 22 nicklas 123   */
6821 29 Aug 22 nicklas 124   public void setSoftware(Software software)
6821 29 Aug 22 nicklas 125   {
6821 29 Aug 22 nicklas 126     this.software = software;
6821 29 Aug 22 nicklas 127   }
6821 29 Aug 22 nicklas 128   
6821 29 Aug 22 nicklas 129   /**
6821 29 Aug 22 nicklas 130     Set the protocol item to set on created RawBioAssay:s
6821 29 Aug 22 nicklas 131     @see RawBioAssay#setProtocol(Protocol)
6821 29 Aug 22 nicklas 132   */
6821 29 Aug 22 nicklas 133   public void setProtocol(Protocol protocol)
6821 29 Aug 22 nicklas 134   {
6821 29 Aug 22 nicklas 135     this.protocol = protocol;
6821 29 Aug 22 nicklas 136   }
6821 29 Aug 22 nicklas 137   
6821 29 Aug 22 nicklas 138   /**
6821 29 Aug 22 nicklas 139     Set the array design item to set on created RawBioAssay:s
6821 29 Aug 22 nicklas 140     @see RawBioAssay#setArrayDesign(ArrayDesign)
6821 29 Aug 22 nicklas 141   */
6821 29 Aug 22 nicklas 142   public void setArrayDesign(ArrayDesign design)
6821 29 Aug 22 nicklas 143   {
6821 29 Aug 22 nicklas 144     this.arrayDesign = design;
6821 29 Aug 22 nicklas 145   }
6821 29 Aug 22 nicklas 146   
6821 29 Aug 22 nicklas 147   /**
6821 29 Aug 22 nicklas 148     Create a child items for all given aligneded sequences and schedule
6821 29 Aug 22 nicklas 149     jobs on the given cluster for running StringTie.
6821 29 Aug 22 nicklas 150     @return A list with the corresponding jobs in BASE
6821 29 Aug 22 nicklas 151   */
6821 29 Aug 22 nicklas 152   public List<JobDefinition> createStringTieJobs(DbControl dc, OpenGridCluster cluster, List<AlignedSequences> alignedSequences)
6821 29 Aug 22 nicklas 153   {
6821 29 Aug 22 nicklas 154     /*
6821 29 Aug 22 nicklas 155     System.out.println("createStringTieJobs:");
6821 29 Aug 22 nicklas 156     System.out.println("software:" + software);
6821 29 Aug 22 nicklas 157     System.out.println("protocol:" + protocol);
6821 29 Aug 22 nicklas 158     System.out.println("design:" + arrayDesign);
6821 29 Aug 22 nicklas 159     */
6821 29 Aug 22 nicklas 160     
6821 29 Aug 22 nicklas 161     SessionControl sc = dc.getSessionControl();
6821 29 Aug 22 nicklas 162     
6821 29 Aug 22 nicklas 163     ClusterConfig clusterCfg = cluster.getConfig();
6821 29 Aug 22 nicklas 164     XmlConfig cfg = Reggie.getConfig(cluster.getId());
6821 29 Aug 22 nicklas 165     if (cfg == null)
6821 29 Aug 22 nicklas 166     {
6821 29 Aug 22 nicklas 167       throw new ItemNotFoundException("No configuration in reggie-config.xml for cluster: " + cluster.getId());
6821 29 Aug 22 nicklas 168     }
6821 29 Aug 22 nicklas 169
6821 29 Aug 22 nicklas 170     String parameterSet = (String)Annotationtype.PARAMETER_SET.getAnnotationValue(dc, software);
6821 29 Aug 22 nicklas 171     
6821 29 Aug 22 nicklas 172     // Get global options
6821 29 Aug 22 nicklas 173     String global_env = ScriptUtil.multilineIndent(cfg.getConfig("global-env"));
6821 29 Aug 22 nicklas 174     String projectArchive = cfg.getRequiredConfig("project-archive", null);
6821 29 Aug 22 nicklas 175     String externalArchive = cfg.getConfig("external-archive", null, projectArchive);
6821 29 Aug 22 nicklas 176
6821 29 Aug 22 nicklas 177     // Options for the programs
7372 06 Oct 23 nicklas 178     String stringtie_submit = cfg.getConfig("stringtie-2023/submit", parameterSet, null);
7372 06 Oct 23 nicklas 179     String stringtie_submit_debug = cfg.getConfig("stringtie-2023/submit-debug", parameterSet, null);
6821 29 Aug 22 nicklas 180     String stringtie_env = ScriptUtil.multilineIndent(cfg.getRequiredConfig("stringtie-2023/env", parameterSet));
6821 29 Aug 22 nicklas 181     String stringtie_envdebug = ScriptUtil.multilineIndent(cfg.getConfig("stringtie-2023/env-debug", parameterSet, null));
6821 29 Aug 22 nicklas 182     String stringtie_execute = ScriptUtil.multilineIndent(cfg.getConfig("stringtie-2023/execute", parameterSet, "./stringtie2023.sh"));
6821 29 Aug 22 nicklas 183
6821 29 Aug 22 nicklas 184     // Selected items must be removed from this list
6821 29 Aug 22 nicklas 185     ItemList stringtiePipeline = BiomaterialList.STRINGTIE_2023_PIPELINE.load(dc);
6821 29 Aug 22 nicklas 186
6821 29 Aug 22 nicklas 187     // Create StringTie raw bioassays
6821 29 Aug 22 nicklas 188     Rawdatatype stringTieType = Rawdatatype.STRINGTIE;
6821 29 Aug 22 nicklas 189
6821 29 Aug 22 nicklas 190     // Options common for all jobs
6821 29 Aug 22 nicklas 191     JobConfig jobConfig = new JobConfig();
6821 29 Aug 22 nicklas 192     if (priority != null) jobConfig.setPriority(priority);
7372 06 Oct 23 nicklas 193     if (partition != null) jobConfig.setSbatchOption("partition", ScriptUtil.checkValidScriptParameter(partition));
7372 06 Oct 23 nicklas 194     jobConfig.convertOptionsTo(clusterCfg.getType());
7372 06 Oct 23 nicklas 195     if (submitOptionsOverride != null)
7372 06 Oct 23 nicklas 196     {
7372 06 Oct 23 nicklas 197       ScriptUtil.addSubmitOptions(jobConfig, submitOptionsOverride, clusterCfg.getType());
7372 06 Oct 23 nicklas 198     }
7372 06 Oct 23 nicklas 199     else
7372 06 Oct 23 nicklas 200     {
7372 06 Oct 23 nicklas 201       ScriptUtil.addSubmitOptions(jobConfig, stringtie_submit, clusterCfg.getType());
7372 06 Oct 23 nicklas 202       if (debug) ScriptUtil.addSubmitOptions(jobConfig, stringtie_submit_debug, clusterCfg.getType());
7372 06 Oct 23 nicklas 203     }
6821 29 Aug 22 nicklas 204     
6821 29 Aug 22 nicklas 205     // We submit one job for each raw bioassay to the cluster
6821 29 Aug 22 nicklas 206     List<JobDefinition> jobDefs = new ArrayList<JobDefinition>(alignedSequences.size());
6821 29 Aug 22 nicklas 207
6821 29 Aug 22 nicklas 208     for (AlignedSequences as : alignedSequences)
6821 29 Aug 22 nicklas 209     {
6821 29 Aug 22 nicklas 210       as = AlignedSequences.getById(dc, as.getId()); // Ensure item is loaded in this transaction
6821 29 Aug 22 nicklas 211
6821 29 Aug 22 nicklas 212       // Get some information about the aligned data that we need
6821 29 Aug 22 nicklas 213       DerivedBioAssay aligned = as.getDerivedBioAssay();
6821 29 Aug 22 nicklas 214       stringtiePipeline.removeItem(aligned);
6821 29 Aug 22 nicklas 215       
6821 29 Aug 22 nicklas 216       Library lib = Library.get(aligned.getExtract());
6821 29 Aug 22 nicklas 217       Sample specimen =  (Sample)lib.findSingleParent(dc, Subtype.SPECIMEN);
6821 29 Aug 22 nicklas 218       boolean isExternal = Reggie.isExternalItem(aligned.getName());
6821 29 Aug 22 nicklas 219       String archiveFolder = isExternal ? externalArchive : projectArchive;
6821 29 Aug 22 nicklas 220       String bamFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, aligned);
6821 29 Aug 22 nicklas 221       File bamFile = Datafiletype.BAM.getFile(dc, aligned);
6821 29 Aug 22 nicklas 222       String bamName = ScriptUtil.checkValidScriptParameter(bamFile.getName());
6821 29 Aug 22 nicklas 223       
6821 29 Aug 22 nicklas 224       int readLength = getAverageReadSize(dc, as);
6821 29 Aug 22 nicklas 225       
6821 29 Aug 22 nicklas 226       // Create job 
6821 29 Aug 22 nicklas 227       Job stringTieJob = Job.getNew(dc, null, null, null);
6821 29 Aug 22 nicklas 228       stringTieJob.setItemSubtype(Subtype.STRINGTIE_JOB.get(dc));
6821 29 Aug 22 nicklas 229       stringTieJob.setPluginVersion("reggie-"+Reggie.VERSION);
6821 29 Aug 22 nicklas 230       stringTieJob.setSendMessage(Values.getBoolean(sc.getUserClientSetting("plugins.sendmessage"), false));
6821 29 Aug 22 nicklas 231       stringTieJob.setName("Run StringTie/2023 " + aligned.getName());
6821 29 Aug 22 nicklas 232       stringTieJob.setParameterValue("pipeline", new StringParameterType(), Pipeline.RNASEQ_STRINGTIE_2023.getId());
6821 29 Aug 22 nicklas 233       if (debug) stringTieJob.setName(stringTieJob.getName() + " (debug)");
6981 17 Jan 23 nicklas 234       if (partition != null) stringTieJob.setParameterValue("partition", new StringParameterType(), partition);
7372 06 Oct 23 nicklas 235       if (submitOptionsOverride != null) stringTieJob.setParameterValue("jobOptions", new StringParameterType(), submitOptionsOverride);
6821 29 Aug 22 nicklas 236       dc.saveItem(stringTieJob);
6821 29 Aug 22 nicklas 237
6821 29 Aug 22 nicklas 238       // Create raw bioassay
6821 29 Aug 22 nicklas 239       String stringTieName = ScriptUtil.checkValidScriptParameter(as.getNextRawBioAssayName(dc, stringTieType));
6821 29 Aug 22 nicklas 240       RawBioAssay raw = stringTieType.createRawBioAssay(dc);
6821 29 Aug 22 nicklas 241       Pipeline.RNASEQ_STRINGTIE_2023.setAnnotation(dc, raw);
6821 29 Aug 22 nicklas 242       raw.setArrayDesign(arrayDesign);
6821 29 Aug 22 nicklas 243       raw.setJob(stringTieJob);
6821 29 Aug 22 nicklas 244       raw.setName(stringTieName);
6821 29 Aug 22 nicklas 245       raw.setParentExtract(lib.getExtract());
6821 29 Aug 22 nicklas 246       raw.setSoftware(software);
6821 29 Aug 22 nicklas 247       raw.setProtocol(protocol);
6821 29 Aug 22 nicklas 248       raw.setParentBioAssay(aligned);
6821 29 Aug 22 nicklas 249       DoNotUse.copyDoNotUseAnnotations(dc, aligned, raw, false);
6821 29 Aug 22 nicklas 250       dc.saveItem(raw);
6821 29 Aug 22 nicklas 251
6821 29 Aug 22 nicklas 252       String stringTieFolder = bamFolder + "/"+raw.getName().substring(aligned.getName().length()+1);
6821 29 Aug 22 nicklas 253       if (debug && !stringTieFolder.startsWith("/debug"))
6821 29 Aug 22 nicklas 254       {
6821 29 Aug 22 nicklas 255         stringTieFolder = "/debug" + stringTieFolder;
6821 29 Aug 22 nicklas 256       }
6821 29 Aug 22 nicklas 257       Annotationtype.DATA_FILES_FOLDER.setAnnotationValue(dc, raw, stringTieFolder);
6821 29 Aug 22 nicklas 258       if (autoConfirm)
6821 29 Aug 22 nicklas 259       {
6821 29 Aug 22 nicklas 260         Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, raw, "AutoConfirm");
6821 29 Aug 22 nicklas 261       }
6821 29 Aug 22 nicklas 262       String externalStringTieName = stringTieName;
6821 29 Aug 22 nicklas 263       if (specimen != null && specimen.getExternalId() != null)
6821 29 Aug 22 nicklas 264       {
6821 29 Aug 22 nicklas 265         // Replace SCANB-ID with Sample.externalId
6821 29 Aug 22 nicklas 266         externalStringTieName = externalStringTieName.replace(specimen.getName(), specimen.getExternalId());
6821 29 Aug 22 nicklas 267       }
6821 29 Aug 22 nicklas 268
6821 29 Aug 22 nicklas 269       // Checks to make sure no bad things are included in script file
6821 29 Aug 22 nicklas 270       ScriptUtil.checkValidPath(stringTieFolder, true, true);
6821 29 Aug 22 nicklas 271       ScriptUtil.checkValidScriptParameter(raw.getName());
6821 29 Aug 22 nicklas 272       ScriptUtil.checkValidScriptParameter(bamFile.getName());
6821 29 Aug 22 nicklas 273
6821 29 Aug 22 nicklas 274       ScriptBuilder script = new ScriptBuilder();
6821 29 Aug 22 nicklas 275       script.cmd(debug ? "set -ex" : "set -e");
6821 29 Aug 22 nicklas 276       // Set file permissions based on consent or external group!
6821 29 Aug 22 nicklas 277       String externalGroup = isExternal ? Reggie.getExternalGroup(aligned.getName()) : null;
6821 29 Aug 22 nicklas 278       ScriptUtil.setUmaskForItem(dc, lib, externalGroup, script);
6821 29 Aug 22 nicklas 279       script.newLine();
6821 29 Aug 22 nicklas 280       script.cmd(global_env);
6821 29 Aug 22 nicklas 281       script.export("ArchiveFolder", archiveFolder);
6821 29 Aug 22 nicklas 282       script.export("BamFolder", "${ArchiveFolder}"+bamFolder);
6821 29 Aug 22 nicklas 283       script.export("BamName", bamName.replace(".bam", ""));
6821 29 Aug 22 nicklas 284       script.export("StringTieFolder", "${ArchiveFolder}"+stringTieFolder);
6821 29 Aug 22 nicklas 285       script.export("ExternalStringTieName", externalStringTieName);
6821 29 Aug 22 nicklas 286       script.export("AvgReadLength", Integer.toString(readLength));
6821 29 Aug 22 nicklas 287       script.newLine();
6821 29 Aug 22 nicklas 288       script.cmd(stringtie_env);
6821 29 Aug 22 nicklas 289       if (debug) script.cmd(stringtie_envdebug);
6821 29 Aug 22 nicklas 290       script.cmd(stringtie_execute);
6821 29 Aug 22 nicklas 291       if (externalGroup != null)
6821 29 Aug 22 nicklas 292       {
6821 29 Aug 22 nicklas 293         ScriptUtil.addChgrp(externalGroup, "${StringTieFolder}", stringTieName, null, script);
6821 29 Aug 22 nicklas 294       }
6821 29 Aug 22 nicklas 295
6821 29 Aug 22 nicklas 296       JobDefinition jobDef = new JobDefinition("StringTie2023", jobConfig, batchConfig, stringTieJob);
6821 29 Aug 22 nicklas 297       jobDef.addFile(ScriptUtil.upload("stringtie2023.sh"));
6821 29 Aug 22 nicklas 298       jobDef.addFile(ScriptUtil.upload("reggie-utils.sh"));
6821 29 Aug 22 nicklas 299       jobDef.addFile(ScriptUtil.upload("stdwrap.sh"));
6821 29 Aug 22 nicklas 300       jobDef.setDebug(debug);
6821 29 Aug 22 nicklas 301       jobDef.setCmd(script.toString());
6821 29 Aug 22 nicklas 302       jobDefs.add(jobDef);
6821 29 Aug 22 nicklas 303     }
6821 29 Aug 22 nicklas 304     
6821 29 Aug 22 nicklas 305     return jobDefs;
6821 29 Aug 22 nicklas 306   }
6821 29 Aug 22 nicklas 307
6821 29 Aug 22 nicklas 308   /**
6821 29 Aug 22 nicklas 309     Job completion handler for StringTie/2023 jobs.
6821 29 Aug 22 nicklas 310   */
6821 29 Aug 22 nicklas 311   public static class StringTieJobCompletionHandler
6821 29 Aug 22 nicklas 312     implements JobCompletionHandler
6821 29 Aug 22 nicklas 313   {
7079 27 Mar 23 nicklas 314     private static final ExtensionsLogger logger = 
7079 27 Mar 23 nicklas 315       ExtensionsLog.getLogger(JobCompletionHandlerFactory.ID, true).wrap(LoggerFactory.getLogger(StringTieJobCompletionHandler.class));
6821 29 Aug 22 nicklas 316     
6821 29 Aug 22 nicklas 317     public StringTieJobCompletionHandler()
6821 29 Aug 22 nicklas 318     {}
6821 29 Aug 22 nicklas 319   
6821 29 Aug 22 nicklas 320     @Override
6821 29 Aug 22 nicklas 321     public String jobCompleted(SessionControl sc, OpenGridSession session, Job job, JobStatus status)
6821 29 Aug 22 nicklas 322     {
6821 29 Aug 22 nicklas 323       String jobName = status.getName();
6821 29 Aug 22 nicklas 324       String files = session.getJobFileAsString(jobName, "files.out", "UTF-8");
6821 29 Aug 22 nicklas 325       String msg = parseFiles(sc, job, files);
6821 29 Aug 22 nicklas 326       return "StringTie/2023 completed. " + msg;
6821 29 Aug 22 nicklas 327     }
6821 29 Aug 22 nicklas 328     
6821 29 Aug 22 nicklas 329     private String parseFiles(SessionControl sc, Job job, String filesOut)
6821 29 Aug 22 nicklas 330     {
6821 29 Aug 22 nicklas 331       
6821 29 Aug 22 nicklas 332       DbControl dc = null;
6821 29 Aug 22 nicklas 333       String msg = null;
6821 29 Aug 22 nicklas 334       try
6821 29 Aug 22 nicklas 335       {
6821 29 Aug 22 nicklas 336         dc = sc.newDbControl("Reggie: StringTie/2023 completed handler");
6821 29 Aug 22 nicklas 337         
6821 29 Aug 22 nicklas 338         Rawbioassay rawStringTie = Rawbioassay.getByJob(dc, job);
6821 29 Aug 22 nicklas 339         RawBioAssay raw = rawStringTie.getItem();
6821 29 Aug 22 nicklas 340
6821 29 Aug 22 nicklas 341         // Create file links
6821 29 Aug 22 nicklas 342         boolean useExternalProjectArchive = Reggie.isExternalItem(raw.getName());
6821 29 Aug 22 nicklas 343         FileServer fileArchive = useExternalProjectArchive ? Fileserver.EXTERNAL_ARCHIVE.load(dc) : Fileserver.PROJECT_ARCHIVE.load(dc);
6821 29 Aug 22 nicklas 344         String analysisDir = useExternalProjectArchive ? Reggie.EXTERNAL_ANALYSIS_DIR : Reggie.SECONDARY_ANALYSIS_DIR;
6821 29 Aug 22 nicklas 345
6821 29 Aug 22 nicklas 346         String dataFilesFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, raw);
6821 29 Aug 22 nicklas 347         String baseFolder = Reggie.convertDataFilesFolderToBaseFolder(dataFilesFolder);
6821 29 Aug 22 nicklas 348         Directory localDataDir = Directory.getNew(dc, new Path(analysisDir+baseFolder, Path.Type.DIRECTORY));
6821 29 Aug 22 nicklas 349   
6821 29 Aug 22 nicklas 350         DataFileType rawData = Datafiletype.GENERIC_RAWDATA.load(dc);
6821 29 Aug 22 nicklas 351         ItemSubtype rawType = rawData.getGenericType();
6821 29 Aug 22 nicklas 352
6821 29 Aug 22 nicklas 353         int lineNo = 0;
6821 29 Aug 22 nicklas 354         for (String line : filesOut.split("\n"))
6821 29 Aug 22 nicklas 355         {
6821 29 Aug 22 nicklas 356           lineNo++;
6821 29 Aug 22 nicklas 357           
6821 29 Aug 22 nicklas 358           File f = File.getFile(dc, localDataDir, line.substring(line.lastIndexOf("/")+1), true);
6821 29 Aug 22 nicklas 359           f.setFileServer(fileArchive);
6821 29 Aug 22 nicklas 360           String fileUrl = "sftp://" + fileArchive.getHost() + dataFilesFolder + "/" + f.getName();
6821 29 Aug 22 nicklas 361           try
6821 29 Aug 22 nicklas 362           {
6821 29 Aug 22 nicklas 363             f.setUrl(fileUrl, true);
6821 29 Aug 22 nicklas 364           }
6821 29 Aug 22 nicklas 365           catch (RuntimeException ex)
6821 29 Aug 22 nicklas 366           {
6821 29 Aug 22 nicklas 367             f.setUrl(fileUrl, false);
6821 29 Aug 22 nicklas 368           }
6821 29 Aug 22 nicklas 369           
6821 29 Aug 22 nicklas 370           if (!f.isInDatabase())
6821 29 Aug 22 nicklas 371           {
6821 29 Aug 22 nicklas 372             dc.saveItem(f);
6821 29 Aug 22 nicklas 373           }
6821 29 Aug 22 nicklas 374           
6821 29 Aug 22 nicklas 375           if (f.getName().equals("gene.tsv"))
6821 29 Aug 22 nicklas 376           {
6821 29 Aug 22 nicklas 377             f.setItemSubtype(rawType);
6821 29 Aug 22 nicklas 378             f.setMimeType("text/plain");
6821 29 Aug 22 nicklas 379             f.setCharacterSet("UTF-8");
6821 29 Aug 22 nicklas 380             FileSetMember member = raw.getFileSet().addMember(f, rawData);
6821 29 Aug 22 nicklas 381             
6821 29 Aug 22 nicklas 382             try
6821 29 Aug 22 nicklas 383             {
6821 29 Aug 22 nicklas 384               int numUniqueGenes = parseAndCountGenesInGeneTsv(f);
6821 29 Aug 22 nicklas 385               member.setValid(true, null);
6821 29 Aug 22 nicklas 386               raw.setNumFileSpots(numUniqueGenes);
6821 29 Aug 22 nicklas 387               msg = numUniqueGenes + " genes found in gene.tsv";
6821 29 Aug 22 nicklas 388             }
6821 29 Aug 22 nicklas 389             catch (IOException | RuntimeException ex)
6821 29 Aug 22 nicklas 390             {
6821 29 Aug 22 nicklas 391               msg = "Could not parse gene.tsv (" + ex.getMessage() + ")";
6821 29 Aug 22 nicklas 392               member.setValid(false, ex.getMessage());
6821 29 Aug 22 nicklas 393               logger.warn("Could not parse file: " + f, ex);
6821 29 Aug 22 nicklas 394             }
6821 29 Aug 22 nicklas 395           }
6821 29 Aug 22 nicklas 396           else
6821 29 Aug 22 nicklas 397           {
6821 29 Aug 22 nicklas 398             AnyToAny link = AnyToAny.getNewOrExisting(dc, raw, f.getName(), f, true);
6821 29 Aug 22 nicklas 399             if (!link.isInDatabase()) dc.saveItem(link);
6821 29 Aug 22 nicklas 400           }
6821 29 Aug 22 nicklas 401
6821 29 Aug 22 nicklas 402         }
6821 29 Aug 22 nicklas 403         
6821 29 Aug 22 nicklas 404         dc.commit();
6821 29 Aug 22 nicklas 405       }
6821 29 Aug 22 nicklas 406       finally
6821 29 Aug 22 nicklas 407       {
6821 29 Aug 22 nicklas 408         if (dc != null) dc.close();
6821 29 Aug 22 nicklas 409       }
6821 29 Aug 22 nicklas 410
6821 29 Aug 22 nicklas 411       return msg == null ? "Could not find gene.tsv" : msg;
6821 29 Aug 22 nicklas 412     }
6821 29 Aug 22 nicklas 413     
6821 29 Aug 22 nicklas 414     /**
6821 29 Aug 22 nicklas 415       Counts the number of unique "Gene ID" values in the
6821 29 Aug 22 nicklas 416       gene.tsv file.
6821 29 Aug 22 nicklas 417     */
6821 29 Aug 22 nicklas 418     private int parseAndCountGenesInGeneTsv(File f)
6821 29 Aug 22 nicklas 419       throws IOException
6821 29 Aug 22 nicklas 420     {
6821 29 Aug 22 nicklas 421       InputStream in = null;
6821 29 Aug 22 nicklas 422       Set<String> genes = new HashSet<>();
6821 29 Aug 22 nicklas 423       try
6821 29 Aug 22 nicklas 424       {
6821 29 Aug 22 nicklas 425         in = f.getDownloadStream(0);
6821 29 Aug 22 nicklas 426         
6821 29 Aug 22 nicklas 427         FlatFileParser ffp = new FlatFileParser();
6821 29 Aug 22 nicklas 428         ffp.setDataHeaderRegexp(Pattern.compile("Gene ID\\t.*"));
6821 29 Aug 22 nicklas 429         ffp.setDataSplitterRegexp(Pattern.compile("\\t"));
6821 29 Aug 22 nicklas 430         
6821 29 Aug 22 nicklas 431         ffp.setInputStream(in, "UTF-8");
6821 29 Aug 22 nicklas 432
6821 29 Aug 22 nicklas 433         LineType headerLine = ffp.parseHeaders();
6821 29 Aug 22 nicklas 434         int lineNo = ffp.getParsedLines();
6821 29 Aug 22 nicklas 435         if (headerLine != LineType.DATA_HEADER)
6821 29 Aug 22 nicklas 436         {
6821 29 Aug 22 nicklas 437           throw new IOException("File '" + f.getName() + "' line " + lineNo + ": Could not find header line starting with 'Gene ID{tab}...'");
6821 29 Aug 22 nicklas 438         }
6821 29 Aug 22 nicklas 439
6821 29 Aug 22 nicklas 440         while (ffp.hasMoreData())
6821 29 Aug 22 nicklas 441         {
6821 29 Aug 22 nicklas 442           FlatFileParser.Data line = ffp.nextData();
6821 29 Aug 22 nicklas 443           String geneId = line.getString(0);
6821 29 Aug 22 nicklas 444           genes.add(geneId);
6821 29 Aug 22 nicklas 445         }
6821 29 Aug 22 nicklas 446       }
6821 29 Aug 22 nicklas 447       finally
6821 29 Aug 22 nicklas 448       {
6821 29 Aug 22 nicklas 449         FileUtil.close(in);
6821 29 Aug 22 nicklas 450       }
6821 29 Aug 22 nicklas 451       return genes.size();
6821 29 Aug 22 nicklas 452     }
6821 29 Aug 22 nicklas 453   }
6821 29 Aug 22 nicklas 454 }