MultiSampleQScript.scala 4.86 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
29
30
  @Argument(doc = "Only Sample", shortName = "sample", required = false)
  val onlySample: List[String] = Nil

Peter van 't Hof's avatar
Peter van 't Hof committed
31
  require(Config.global.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
43
44
    /**
     * Library class with basic functions build in
     * @param libraryId
     */
Peter van 't Hof's avatar
Peter van 't Hof committed
45
    abstract class AbstractLibrary(val libraryId: String) {
Peter van 't Hof's avatar
Peter van 't Hof committed
46
      /** Overrules config of qscript with default sample and default library */
Peter van 't Hof's avatar
Peter van 't Hof committed
47
      val config = new ConfigFunctions(defaultSample = sampleId, defaultLibrary = libraryId)
Peter van 't Hof's avatar
Peter van 't Hof committed
48
49
50
      
      /** Adds the library jobs */
      final def add(): Unit = {
51
        currentSample = Some(sampleId)
Peter van 't Hof's avatar
Peter van 't Hof committed
52
53
54
        currentLib = Some(libraryId)
        addJobs()
        currentLib = None
55
56
57
        currentSample = None
      }

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

      /** Returns library directory */
      def libDir = sampleDir + "lib_" + libraryId + File.separator
63

Peter van 't Hof's avatar
Peter van 't Hof committed
64
65
      /** Function that add library jobs */
      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
84
      ConfigUtils.getMapFromPath(Config.global.map, List("samples", sampleId, "libraries")).getOrElse(Map()).keySet
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
85

Peter van 't Hof's avatar
Peter van 't Hof committed
86
87
    /** Adds sample jobs */
    final def add(): 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
94
    /** Function to add library jobs */
    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 runs all libraries in one call */
97
98
    protected final def runLibraryJobs(): Unit = {
      for ((libraryId, library) <- libraries) {
Peter van 't Hof's avatar
Peter van 't Hof committed
99
        library.add()
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
111
    /**
     * Creates a sample file with given suffix
     * @param suffix
     * @return
     */
    def createFile(suffix: String) = new File(sampleDir, sampleId + suffix)

    /** Returns sample directory */
    def sampleDir = outputDir + "samples" + File.pathSeparator + sampleId + File.pathSeparator
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
119
120
121
122
  /**
   * Factory method for Sample class
    * @param id SampleId
   * @return Sample class
   */
   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 */
Peter van 't Hof's avatar
Peter van 't Hof committed
128
129
  protected def sampleIds: Set[String] = if (onlySample != Nil) onlySample.toSet else {
    ConfigUtils.any2map(Config.global.map("samples")).keySet
130
131
  }

132
133
134
  /** Runs runSingleSampleJobs method for each sample */
  final def runSamplesJobs() {
    for ((sampleId, sample) <- samples) {
Peter van 't Hof's avatar
Peter van 't Hof committed
135
      sample.add()
136
    }
137
138
  }

Peter van 't Hof's avatar
Peter van 't Hof committed
139
  /** Stores sample state */
140
141
  private var currentSample: Option[String] = None

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