BiopetCommandLineFunctionTrait.scala 5.83 KB
Newer Older
1
2
package nl.lumc.sasc.biopet.core

3
//import java.io.BufferedInputStream
4
import java.io.File
Peter van 't Hof's avatar
Peter van 't Hof committed
5
import nl.lumc.sasc.biopet.core.config.Configurable
Peter van 't Hof's avatar
Peter van 't Hof committed
6
7
import org.broadinstitute.gatk.queue.QException
import org.broadinstitute.gatk.queue.function.CommandLineFunction
8
import org.broadinstitute.gatk.utils.commandline.{ Input, Argument }
9
//import scala.io.Source
10
import scala.sys.process.{ Process, ProcessLogger }
11
import scala.util.matching.Regex
12
13
import java.io.FileInputStream
import java.security.MessageDigest
14
15

trait BiopetCommandLineFunctionTrait extends CommandLineFunction with Configurable {
Peter van 't Hof's avatar
Peter van 't Hof committed
16
  analysisName = configName
bow's avatar
bow committed
17
18

  @Input(doc = "deps", required = false)
19
  var deps: List[File] = Nil
bow's avatar
bow committed
20
21

  @Argument(doc = "Threads", required = false)
22
23
  var threads = 0
  val defaultThreads = 1
bow's avatar
bow committed
24
25

  @Argument(doc = "Vmem", required = false)
26
27
  var vmem: String = _
  val defaultVmem: String = ""
bow's avatar
bow committed
28

Peter van 't Hof's avatar
Peter van 't Hof committed
29
  @Argument(doc = "Executable", required = false)
Peter van 't Hof's avatar
Peter van 't Hof committed
30
  var executable: String = _
bow's avatar
bow committed
31

32
  protected[core] def beforeCmd {
33
  }
bow's avatar
bow committed
34

35
  protected[core] def afterGraph {
36
  }
bow's avatar
bow committed
37

38
  override def freezeFieldValues() {
Peter van 't Hof's avatar
Peter van 't Hof committed
39
    checkExecutable
40
    afterGraph
Peter van 't Hof's avatar
Peter van 't Hof committed
41
    jobOutputFile = new File(firstOutput.getParent + "/." + firstOutput.getName + "." + configName + ".out")
bow's avatar
bow committed
42

43
44
    if (threads == 0) threads = getThreads(defaultThreads)
    if (threads > 1) nCoresRequest = Option(threads)
bow's avatar
bow committed
45

46
    if (vmem == null) {
Peter van 't Hof's avatar
Peter van 't Hof committed
47
48
      vmem = config("vmem")
      if (vmem == null && !defaultVmem.isEmpty) vmem = defaultVmem
49
50
    }
    if (vmem != null) jobResourceRequests :+= "h_vmem=" + vmem
Peter van 't Hof's avatar
Peter van 't Hof committed
51
    jobName = configName + ":" + firstOutput.getName
bow's avatar
bow committed
52

53
54
    super.freezeFieldValues()
  }
bow's avatar
bow committed
55

Peter van 't Hof's avatar
Peter van 't Hof committed
56
  protected def checkExecutable {
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
    if (!BiopetCommandLineFunctionTrait.executableMd5Cache.contains(executable)) {
      try if (executable != null) {
        if (!BiopetCommandLineFunctionTrait.executableCache.contains(executable)) {
          val oldExecutable = executable
          val buffer = new StringBuffer()
          val cmd = Seq("which", executable)
          val process = Process(cmd).run(ProcessLogger(buffer.append(_)))
          if (process.exitValue == 0) {
            executable = buffer.toString
            val file = new File(executable)
            executable = file.getCanonicalPath
          } else {
            logger.error("executable: '" + executable + "' not found, please check config")
            throw new QException("executable: '" + executable + "' not found, please check config")
          }
          BiopetCommandLineFunctionTrait.executableCache += oldExecutable -> executable
          BiopetCommandLineFunctionTrait.executableCache += executable -> executable
        } else {
          executable = BiopetCommandLineFunctionTrait.executableCache(executable)
        }

        if (!BiopetCommandLineFunctionTrait.executableMd5Cache.contains(executable)) {
          val is = new FileInputStream(executable)
          val cnt = is.available
          val bytes = Array.ofDim[Byte](cnt)
          is.read(bytes)
          is.close()
          val temp = MessageDigest.getInstance("MD5").digest(bytes).map("%02X".format(_)).mkString.toLowerCase
          BiopetCommandLineFunctionTrait.executableMd5Cache += executable -> temp
        }

        addJobReportBinding("md5sum_exe", BiopetCommandLineFunctionTrait.executableMd5Cache(executable))
      } catch {
        case ioe: java.io.IOException => logger.warn("Could not use 'which', check on executable skipped: " + ioe)
91
      }
92
93
    } else {
      addJobReportBinding("md5sum_exe", BiopetCommandLineFunctionTrait.executableMd5Cache(executable))
94
95
    }
  }
bow's avatar
bow committed
96

97
  final protected def preCmdInternal {
Peter van 't Hof's avatar
Peter van 't Hof committed
98
    checkExecutable
bow's avatar
bow committed
99

100
    beforeCmd
bow's avatar
bow committed
101

102
    addJobReportBinding("cores", if (nCoresRequest.get.toInt > 0) nCoresRequest.get.toInt else 1)
103
    addJobReportBinding("version", getVersion)
104
  }
bow's avatar
bow committed
105

106
  protected def versionCommand: String = null
107
  protected val versionRegex: Regex = null
108
  protected val versionExitcode = List(0) // Can select multiple
Peter van 't Hof's avatar
Peter van 't Hof committed
109
  private def getVersionInternal: String = {
110
    if (versionCommand == null || versionRegex == null) return "N/A"
111
112
    val stdout = new StringBuffer()
    val stderr = new StringBuffer()
113
114
115
116
    def outputLog = "Version command: \n" + versionCommand +
      "\n output log: \n stdout: \n" + stdout.toString +
      "\n stderr: \n" + stderr.toString
    val process = Process(versionCommand).run(ProcessLogger(stdout append _ + "\n", stderr append _ + "\n"))
117
    if (!versionExitcode.contains(process.exitValue)) {
118
      logger.warn("getVersion give exit code " + process.exitValue + ", version not found \n" + outputLog)
119
120
      return "N/A"
    }
121
    for (line <- stdout.toString.split("\n") ++ stderr.toString.split("\n")) {
bow's avatar
bow committed
122
      line match {
123
        case versionRegex(m) => return m
Peter van 't Hof's avatar
Peter van 't Hof committed
124
        case _               =>
125
126
      }
    }
127
    logger.warn("getVersion give a exit code " + process.exitValue + " but no version was found, executable correct? \n" + outputLog)
128
129
    return "N/A"
  }
bow's avatar
bow committed
130

Peter van 't Hof's avatar
Peter van 't Hof committed
131
132
133
134
135
136
  def getVersion: String = {
    if (!BiopetCommandLineFunctionTrait.versionCache.contains(executable))
      BiopetCommandLineFunctionTrait.versionCache += executable -> getVersionInternal
    return BiopetCommandLineFunctionTrait.versionCache(executable)
  }

bow's avatar
bow committed
137
138
139
  def getThreads(default: Int): Int = {
    val maxThreads: Int = config("maxthreads", default = 8)
    val threads: Int = config("threads", default = default)
140
141
142
    if (maxThreads > threads) return threads
    else return maxThreads
  }
bow's avatar
bow committed
143
144
145
146

  def getThreads(default: Int, module: String): Int = {
    val maxThreads: Int = config("maxthreads", default = 8, submodule = module)
    val threads: Int = config("threads", default = default, submodule = module)
147
148
149
150
    if (maxThreads > threads) return threads
    else return maxThreads
  }
}
Peter van 't Hof's avatar
Peter van 't Hof committed
151
152
153
154

object BiopetCommandLineFunctionTrait {
  import scala.collection.mutable.Map
  private val versionCache: Map[String, String] = Map()
155
156
  private val executableMd5Cache: Map[String, String] = Map()
  private val executableCache: Map[String, String] = Map()
Peter van 't Hof's avatar
Peter van 't Hof committed
157
}