MultiSampleQScript.scala 5.76 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.summary.{ SummaryQScript, Summarizable }
21
import nl.lumc.sasc.biopet.utils.ConfigUtils
22
import org.broadinstitute.gatk.utils.commandline.Argument
23

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

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

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

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

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

Peter van 't Hof's avatar
Peter van 't Hof committed
43
      /** Name overules the one from qscript */
44
45
46
47
      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
48
      /** Adds the library jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
49
      final def addAndTrackJobs(): Unit = {
50
        currentSample = Some(sampleId)
51
        currentLib = Some(libId)
Peter van 't Hof's avatar
Peter van 't Hof committed
52
        addJobs()
53
        qscript.addSummarizable(this, "pipeline", Some(sampleId), Some(libId))
Peter van 't Hof's avatar
Peter van 't Hof committed
54
        currentLib = None
55
56
57
        currentSample = None
      }

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

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

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

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

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

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

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

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

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

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

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

109
    /** Creates a sample file with given suffix */
Peter van 't Hof's avatar
Peter van 't Hof committed
110
111
112
    def createFile(suffix: String) = new File(sampleDir, sampleId + suffix)

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

Peter van 't Hof's avatar
Peter van 't Hof committed
116
  /** Sample type, need implementation in pipeline */
Peter van 't Hof's avatar
Peter van 't Hof committed
117
118
  type Sample <: AbstractSample

Peter van 't Hof's avatar
Peter van 't Hof committed
119
120
  /**
   * Factory method for Sample class
121
   * @param id SampleId
Peter van 't Hof's avatar
Peter van 't Hof committed
122
123
   * @return Sample class
   */
124
  def makeSample(id: String): Sample
Peter van 't Hof's avatar
Peter van 't Hof committed
125

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

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

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

143
  /**
Peter van 't Hof's avatar
Peter van 't Hof committed
144
   * Method where the multisample jobs should be added, this will be executed only when running the -sample argument is not given.
145
146
147
   */
  def addMultiSampleJobs()

Peter van 't Hof's avatar
Peter van 't Hof committed
148
  /** Stores sample state */
149
150
  private var currentSample: Option[String] = None

Peter van 't Hof's avatar
Peter van 't Hof committed
151
152
153
154
  /** 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 */
155
  override protected[core] def configFullPath: List[String] = {
156
    val sample = currentSample match {
Peter van 't Hof's avatar
Peter van 't Hof committed
157
158
159
      case Some(s) => "samples" :: s :: Nil
      case _       => Nil
    }
160
    val lib = currentLib match {
Peter van 't Hof's avatar
Peter van 't Hof committed
161
162
163
      case Some(l) => "libraries" :: l :: Nil
      case _       => Nil
    }
164
    sample ::: lib ::: super.configFullPath
165
  }
166
}