MultiSampleQScript.scala 5.24 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.utils.ConfigUtils
Peter van 't Hof's avatar
Peter van 't Hof committed
22
import org.broadinstitute.gatk.utils.commandline.{ Argument }
23

Peter van 't Hof's avatar
Peter van 't Hof committed
24
25
26
/**
 * This trait creates a structured way of use multisample pipelines
 */
27
trait MultiSampleQScript extends BiopetQScript {
Peter van 't Hof's avatar
Peter van 't Hof committed
28
  @Argument(doc = "Only Sample", shortName = "sample", required = false)
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
34
35
36
  /**
   * Sample class with basic functions build in
   * @param sampleId
   */
Peter van 't Hof's avatar
Peter van 't Hof committed
37
  abstract class AbstractSample(val sampleId: String) {
Peter van 't Hof's avatar
Peter van 't Hof committed
38
    /** Overrules config of qscript with default sample */
Peter van 't Hof's avatar
Peter van 't Hof committed
39
    val config = new ConfigFunctions(defaultSample = sampleId)
Peter van 't Hof's avatar
Peter van 't Hof committed
40

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

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()
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 */
62
      def libDir = sampleDir + "lib_" + libId + File.separator
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
    /** Adds sample jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
87
    final def addAndTrackJobs(): Unit = {
88
      currentSample = Some(sampleId)
Peter van 't Hof's avatar
Peter van 't Hof committed
89
      addJobs()
90
91
      currentSample = None
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
92

Peter van 't Hof's avatar
Peter van 't Hof committed
93
    /** Function to add sample jobs */
Peter van 't Hof's avatar
Peter van 't Hof committed
94
    protected def addJobs()
Peter van 't Hof's avatar
Peter van 't Hof committed
95

Peter van 't Hof's avatar
Peter van 't Hof committed
96
    /** function add all libraries in one call */
97
    protected final def addPerLibJobs(): Unit = {
98
      for ((libId, library) <- libraries) {
Peter van 't Hof's avatar
Peter van 't Hof committed
99
        library.addAndTrackJobs()
100
      }
bow's avatar
bow committed
101
102
    }

Peter van 't Hof's avatar
Peter van 't Hof committed
103
104
105
106
107
108
109
110
    /**
     * Creates a sample file with given suffix
     * @param suffix
     * @return
     */
    def createFile(suffix: String) = new File(sampleDir, sampleId + suffix)

    /** Returns sample directory */
111
    def sampleDir = outputDir + "samples" + File.separator + sampleId + File.separator
112
113
  }

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

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

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

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

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

141
142
143
144
145
  /**
   * Method where the multisample jobs should be added, this will be executed only when running the -sample argument is not given
   */
  def addMultiSampleJobs()

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

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