BiopetQScript.scala 4.73 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Biopet is built on top of GATK Queue for building bioinformatic
 * pipelines. It is mainly intended to support LUMC SHARK cluster which is running
 * SGE. But other types of HPC that are supported by GATK Queue (such as PBS)
 * should also be able to execute Biopet tools and pipelines.
 *
 * Copyright 2014 Sequencing Analysis Support Core - Leiden University Medical Center
 *
 * Contact us at: sasc@lumc.nl
 *
 * A dual licensing mode is applied. The source code within this project that are
 * not part of GATK Queue is freely available for non-commercial use under an AGPL
 * license; For commercial users or users who do not want to follow the AGPL
 * license, please contact us to obtain a separate license.
 */
16
17
18
package nl.lumc.sasc.biopet.core

import java.io.File
Peter van 't Hof's avatar
Peter van 't Hof committed
19
import java.io.PrintWriter
20
import nl.lumc.sasc.biopet.core.config.{ ConfigValueIndex, Config, Configurable }
21
import nl.lumc.sasc.biopet.core.report.{ ReportBuilderExtension, ReportBuilder }
Peter van 't Hof's avatar
Peter van 't Hof committed
22
import org.broadinstitute.gatk.utils.commandline.Argument
Peter van 't Hof's avatar
Peter van 't Hof committed
23
24
import org.broadinstitute.gatk.queue.QSettings
import org.broadinstitute.gatk.queue.function.QFunction
25
import org.broadinstitute.gatk.queue.function.scattergather.ScatterGatherableFunction
26
import org.broadinstitute.gatk.queue.util.{ Logging => GatkLogging }
27
import scala.collection.mutable.ListBuffer
28

Peter van 't Hof's avatar
Peter van 't Hof committed
29
/** Base for biopet pipeline */
30
trait BiopetQScript extends Configurable with GatkLogging {
31

32
  @Argument(doc = "JSON / YAML config file(s)", fullName = "config_file", shortName = "config", required = false)
33
  val configfiles: List[File] = Nil
bow's avatar
bow committed
34

35
  @Argument(doc = "Config values, value should be formatted like 'key=value' or 'path:path:key=value'", fullName = "config_value", shortName = "cv", required = false)
36
37
  val configValues: List[String] = Nil

Peter van 't Hof's avatar
Peter van 't Hof committed
38
  /** Output directory of pipeline */
Peter van 't Hof's avatar
Peter van 't Hof committed
39
  var outputDir: File = {
Peter van 't Hof's avatar
Peter van 't Hof committed
40
41
    if (config.contains("output_dir", path = Nil)) config("output_dir", path = Nil).asFile
    else new File(".")
42
  }
bow's avatar
bow committed
43

44
  @Argument(doc = "Disable all scatters", shortName = "DSC", required = false)
45
  var disableScatter: Boolean = false
46

bow's avatar
bow committed
47
48
  var outputFiles: Map[String, File] = Map()

Peter van 't Hof's avatar
Peter van 't Hof committed
49
  /** Get implemented from org.broadinstitute.gatk.queue.QScript */
Peter van 't Hof's avatar
Peter van 't Hof committed
50
  var qSettings: QSettings
bow's avatar
bow committed
51

Peter van 't Hof's avatar
Peter van 't Hof committed
52
53
54
55
  /** Get implemented from org.broadinstitute.gatk.queue.QScript */
  var functions: Seq[QFunction]

  /** Init for pipeline */
56
  def init
bow's avatar
bow committed
57

Peter van 't Hof's avatar
Peter van 't Hof committed
58
59
  /** Pipeline itself */
  def biopetScript
Peter van 't Hof's avatar
Peter van 't Hof committed
60

61
62
63
  /** Returns the extension to make the report */
  def reportClass: Option[ReportBuilderExtension] = None

Peter van 't Hof's avatar
Peter van 't Hof committed
64
  /** Script from queue itself, final to force some checks for each pipeline and write report */
65
  final def script() {
Peter van 't Hof's avatar
Peter van 't Hof committed
66
67
    outputDir = config("output_dir")
    outputDir = outputDir.getAbsoluteFile
68
69
    init
    biopetScript
70

71
    if (disableScatter) for (function <- functions) function match {
72
73
74
      case f: ScatterGatherableFunction => f.scatterCount = 1
      case _                            =>
    }
75
    for (function <- functions) function match {
76
      case f: BiopetCommandLineFunctionTrait => {
77
        f.preProcesExecutable
78
        f.beforeGraph
Peter van 't Hof's avatar
Peter van 't Hof committed
79
        f.commandLine
80
      }
Peter van 't Hof's avatar
Peter van 't Hof committed
81
      case _ =>
82
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
83

Peter van 't Hof's avatar
Peter van 't Hof committed
84
85
86
    if (outputDir.getParentFile.canWrite || (outputDir.exists && outputDir.canWrite))
      globalConfig.writeReport(qSettings.runName, new File(outputDir, ".log/" + qSettings.runName))
    else BiopetQScript.addError("Parent of output dir: '" + outputDir.getParent + "' is not writeable, outputdir can not be created")
87

88
89
    reportClass.foreach(add(_))

90
    BiopetQScript.checkErrors
91
  }
bow's avatar
bow committed
92

Peter van 't Hof's avatar
Peter van 't Hof committed
93
94
95
  /** Get implemented from org.broadinstitute.gatk.queue.QScript */
  def add(functions: QFunction*)

96
  /** Get implemented from org.broadinstitute.gatk.queue.QScript */
Peter van 't Hof's avatar
Peter van 't Hof committed
97
  def addAll(functions: scala.Traversable[org.broadinstitute.gatk.queue.function.QFunction])
98

Peter van 't Hof's avatar
Peter van 't Hof committed
99
100
101
102
103
  /**
   * Function to set isIntermediate and add in 1 line
   * @param function
   * @param isIntermediate
   */
bow's avatar
bow committed
104
  def add(function: QFunction, isIntermediate: Boolean = false) {
105
106
107
    function.isIntermediate = isIntermediate
    add(function)
  }
108
}
109
110
111
112

object BiopetQScript extends Logging {
  private val errors: ListBuffer[Exception] = ListBuffer()

113
114
  def addError(error: String, debug: String = null): Unit = {
    val msg = error + (if (debug != null && logger.isDebugEnabled) "; " + debug else "")
115
116
117
118
119
    errors.append(new Exception(msg))
  }

  protected def checkErrors: Unit = {
    if (!errors.isEmpty) {
120
121
122
123
124
125
126
127
      logger.error("*************************")
      logger.error("Biopet found some errors:")
      if (logger.isDebugEnabled) {
        for (e <- errors) {
          logger.error(e.getMessage)
          logger.debug(e.getStackTrace.mkString("Stack trace:\n", "\n", "\n"))
        }
      } else {
Peter van 't Hof's avatar
Peter van 't Hof committed
128
        errors.map(_.getMessage).sorted.distinct.foreach(logger.error(_))
129
130
131
132
      }
      throw new IllegalStateException("Biopet found errors")
    }
  }
133
}