MultiSampleQScript.scala 5.83 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
package nl.lumc.sasc.biopet.core

18
19
import java.io.File

20
import nl.lumc.sasc.biopet.core.config.{ Config }
21
import nl.lumc.sasc.biopet.core.summary.{ SummaryQScript, Summarizable }
22
import nl.lumc.sasc.biopet.utils.ConfigUtils
Peter van 't Hof's avatar
Peter van 't Hof committed
23
import org.broadinstitute.gatk.utils.commandline.{ Argument }
24

Peter van 't Hof's avatar
Peter van 't Hof committed
25
/** This trait creates a structured way of use multisample pipelines */
26
27
28
trait MultiSampleQScript extends SummaryQScript {
  qscript =>

Peter van 't Hof's avatar
Peter van 't Hof committed
29
  @Argument(doc = "Only Sample", shortName = "sample", required = false)
30
  private val onlySamples: List[String] = Nil
Peter van 't Hof's avatar
Peter van 't Hof committed
31

32
  require(globalConfig.map.contains("samples"), "No Samples found in config")
Peter van 't Hof's avatar
Peter van 't Hof committed
33

Peter van 't Hof's avatar
Peter van 't Hof committed
34
  /** Sample class with basic functions build in */
35
  abstract class AbstractSample(val sampleId: String) extends Summarizable {
Peter van 't Hof's avatar
Peter van 't Hof committed
36
    /** Overrules config of qscript with default sample */
Peter van 't Hof's avatar
Peter van 't Hof committed
37
    val config = new ConfigFunctions(defaultSample = sampleId)
Peter van 't Hof's avatar
Peter van 't Hof committed
38

Peter van 't Hof's avatar
Peter van 't Hof committed
39
    /** Library class with basic functions build in */
40
    abstract class AbstractLibrary(val libId: String) extends Summarizable {
Peter van 't Hof's avatar
Peter van 't Hof committed
41
      /** Overrules config of qscript with default sample and default library */
42
      val config = new ConfigFunctions(defaultSample = sampleId, defaultLibrary = libId)
43

Peter van 't Hof's avatar
Peter van 't Hof committed
44
      /** Name overules the one from qscript */
45
46
47
48
      def addSummarizable(summarizable: Summarizable, name: String): Unit = {
        qscript.addSummarizable(summarizable, name, Some(sampleId), Some(libId))
      }

Peter van 't Hof's avatar
Peter van 't Hof committed
49
      /** Adds the library jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
50
      final def addAndTrackJobs(): Unit = {
51
        currentSample = Some(sampleId)
52
        currentLib = Some(libId)
Peter van 't Hof's avatar
Peter van 't Hof committed
53
        addJobs()
54
        qscript.addSummarizable(this, "pipeline", Some(sampleId), Some(libId))
Peter van 't Hof's avatar
Peter van 't Hof committed
55
        currentLib = None
56
57
58
        currentSample = None
      }

Peter van 't Hof's avatar
Peter van 't Hof committed
59
      /** Creates a library file with given suffix */
60
      def createFile(suffix: String): File = new File(libDir, sampleId + "-" + libId + suffix)
Peter van 't Hof's avatar
Peter van 't Hof committed
61
62

      /** Returns library directory */
Peter van 't Hof's avatar
Peter van 't Hof committed
63
      def libDir = new File(sampleDir, "lib_" + libId)
64

Peter van 't Hof's avatar
Peter van 't Hof committed
65
      /** Function that add library jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
66
      protected def addJobs()
67
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
68

Peter van 't Hof's avatar
Peter van 't Hof committed
69
    /** Library type, need implementation in pipeline */
70
    type Library <: AbstractLibrary
Peter van 't Hof's avatar
Peter van 't Hof committed
71

Peter van 't Hof's avatar
Peter van 't Hof committed
72
73
    /** Stores all libraries */
    val libraries: Map[String, Library] = libIds.map(id => id -> makeLibrary(id)).toMap
74

Peter van 't Hof's avatar
Peter van 't Hof committed
75
76
77
78
79
    /**
     * Factory method for Library class
     * @param id SampleId
     * @return Sample class
     */
Peter van 't Hof's avatar
Peter van 't Hof committed
80
    def makeLibrary(id: String): Library
Peter van 't Hof's avatar
Peter van 't Hof committed
81

Peter van 't Hof's avatar
Peter van 't Hof committed
82
83
    /** returns a set with library names */
    protected def libIds: Set[String] = {
84
      ConfigUtils.getMapFromPath(globalConfig.map, List("samples", sampleId, "libraries")).getOrElse(Map()).keySet
85
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
86

Peter van 't Hof's avatar
Peter van 't Hof committed
87
    /** Name overules the one from qscript */
88
89
90
91
    def addSummarizable(summarizable: Summarizable, name: String): Unit = {
      qscript.addSummarizable(summarizable, name, Some(sampleId))
    }

Peter van 't Hof's avatar
Peter van 't Hof committed
92
    /** Adds sample jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
93
    final def addAndTrackJobs(): Unit = {
94
      currentSample = Some(sampleId)
Peter van 't Hof's avatar
Peter van 't Hof committed
95
      addJobs()
96
      qscript.addSummarizable(this, "pipeline", Some(sampleId))
97
98
      currentSample = None
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
99

Peter van 't Hof's avatar
Peter van 't Hof committed
100
    /** Function to add sample jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
101
    protected def addJobs()
Peter van 't Hof's avatar
Peter van 't Hof committed
102

Peter van 't Hof's avatar
Peter van 't Hof committed
103
    /** function add all libraries in one call */
104
    protected final def addPerLibJobs(): Unit = {
105
      for ((libId, library) <- libraries) {
Peter van 't Hof's avatar
Peter van 't Hof committed
106
        library.addAndTrackJobs()
107
      }
bow's avatar
bow committed
108
109
    }

Peter van 't Hof's avatar
Peter van 't Hof committed
110
111
112
113
114
115
116
117
    /**
     * Creates a sample file with given suffix
     * @param suffix
     * @return
     */
    def createFile(suffix: String) = new File(sampleDir, sampleId + suffix)

    /** Returns sample directory */
Peter van 't Hof's avatar
Peter van 't Hof committed
118
    def sampleDir = new File(outputDir, "samples" + File.separator + sampleId)
119
120
  }

Peter van 't Hof's avatar
Peter van 't Hof committed
121
  /** Sample type, need implementation in pipeline */
Peter van 't Hof's avatar
Peter van 't Hof committed
122
123
  type Sample <: AbstractSample

Peter van 't Hof's avatar
Peter van 't Hof committed
124
125
  /**
   * Factory method for Sample class
126
   * @param id SampleId
Peter van 't Hof's avatar
Peter van 't Hof committed
127
128
   * @return Sample class
   */
129
  def makeSample(id: String): Sample
Peter van 't Hof's avatar
Peter van 't Hof committed
130

Peter van 't Hof's avatar
Peter van 't Hof committed
131
132
  /** Stores all samples */
  val samples: Map[String, Sample] = sampleIds.map(id => id -> makeSample(id)).toMap
133

134
  /** Returns a list of all sampleIDs */
135
  protected def sampleIds: Set[String] = ConfigUtils.any2map(globalConfig.map("samples")).keySet
136

Peter van 't Hof's avatar
Peter van 't Hof committed
137
  /** Runs addAndTrackJobs method for each sample */
Peter van 't Hof's avatar
Peter van 't Hof committed
138
  final def addSamplesJobs() {
139
140
141
142
    if (onlySamples.isEmpty) {
      samples.foreach { case (sampleId, sample) => sample.addAndTrackJobs() }
      addMultiSampleJobs()
    } else onlySamples.foreach(sampleId => samples.get(sampleId) match {
143
144
145
      case Some(sample) => sample.addAndTrackJobs()
      case None         => logger.warn("sampleId '" + sampleId + "' not found")
    })
146
147
  }

148
  /**
Peter van 't Hof's avatar
Peter van 't Hof committed
149
   * Method where the multisample jobs should be added, this will be executed only when running the -sample argument is not given.
150
151
152
   */
  def addMultiSampleJobs()

Peter van 't Hof's avatar
Peter van 't Hof committed
153
  /** Stores sample state */
154
155
  private var currentSample: Option[String] = None

Peter van 't Hof's avatar
Peter van 't Hof committed
156
157
158
159
  /** Stores library state */
  private var currentLib: Option[String] = None

  /** Prefix full path with sample and library for jobs that's are created in current state */
160
  override protected[core] def configFullPath: List[String] = {
Peter van 't Hof's avatar
Peter van 't Hof committed
161
162
163
164
    val s = currentSample match {
      case Some(s) => "samples" :: s :: Nil
      case _       => Nil
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
165
    val l = currentLib match {
Peter van 't Hof's avatar
Peter van 't Hof committed
166
167
168
169
      case Some(l) => "libraries" :: l :: Nil
      case _       => Nil
    }
    s ::: l ::: super.configFullPath
170
  }
171
}