2011-03-11 03:54:14 +08:00
|
|
|
/*
|
2013-01-11 06:44:42 +08:00
|
|
|
* Copyright (c) 2012 The Broad Institute
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person
|
|
|
|
|
* obtaining a copy of this software and associated documentation
|
|
|
|
|
* files (the "Software"), to deal in the Software without
|
|
|
|
|
* restriction, including without limitation the rights to use,
|
|
|
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following
|
|
|
|
|
* conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be
|
|
|
|
|
* included in all copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
|
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
|
|
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
2011-03-11 03:54:14 +08:00
|
|
|
|
2010-06-15 12:43:46 +08:00
|
|
|
package org.broadinstitute.sting.queue
|
|
|
|
|
|
2011-08-24 04:51:54 +08:00
|
|
|
import engine.JobRunInfo
|
2010-10-16 04:00:35 +08:00
|
|
|
import org.broadinstitute.sting.queue.function.QFunction
|
2011-03-11 03:54:14 +08:00
|
|
|
import annotation.target.field
|
2012-10-16 03:29:40 +08:00
|
|
|
import util._
|
2012-10-17 06:49:10 +08:00
|
|
|
import org.broadinstitute.sting.commandline.ArgumentSource
|
2010-06-15 12:43:46 +08:00
|
|
|
|
|
|
|
|
/**
|
2010-08-10 00:42:48 +08:00
|
|
|
* Defines a Queue pipeline as a collection of CommandLineFunctions.
|
2010-06-15 12:43:46 +08:00
|
|
|
*/
|
2011-04-12 04:22:44 +08:00
|
|
|
trait QScript extends Logging with PrimitiveOptionConversions with StringFileConversions {
|
2011-03-24 22:03:51 +08:00
|
|
|
|
2010-06-15 12:43:46 +08:00
|
|
|
// Type aliases so users don't have to import
|
|
|
|
|
type File = java.io.File
|
|
|
|
|
type CommandLineFunction = org.broadinstitute.sting.queue.function.CommandLineFunction
|
2010-10-16 04:00:35 +08:00
|
|
|
type InProcessFunction = org.broadinstitute.sting.queue.function.InProcessFunction
|
2010-06-23 02:39:20 +08:00
|
|
|
type ScatterGatherableFunction = org.broadinstitute.sting.queue.function.scattergather.ScatterGatherableFunction
|
|
|
|
|
type SimpleTextGatherFunction = org.broadinstitute.sting.queue.function.scattergather.SimpleTextGatherFunction
|
2010-06-15 12:43:46 +08:00
|
|
|
|
2011-03-11 03:54:14 +08:00
|
|
|
// Make sure annotations can be used in class constructors but target the fields
|
|
|
|
|
// ex: class MyClass(@Input var myVar: File) {}
|
|
|
|
|
// This was implicitly enabled in 2.8.0-RC2 and then updated to this new syntax:
|
|
|
|
|
// http://lampsvn.epfl.ch/trac/scala/ticket/3596
|
|
|
|
|
// http://lampsvn.epfl.ch/trac/scala/ticket/3421
|
|
|
|
|
type Input = org.broadinstitute.sting.commandline.Input @field
|
|
|
|
|
type Output = org.broadinstitute.sting.commandline.Output @field
|
|
|
|
|
type Argument = org.broadinstitute.sting.commandline.Argument @field
|
|
|
|
|
type ArgumentCollection = org.broadinstitute.sting.commandline.ArgumentCollection @field
|
2011-03-24 22:03:51 +08:00
|
|
|
type Gather = org.broadinstitute.sting.commandline.Gather @field
|
2011-03-11 03:54:14 +08:00
|
|
|
|
2012-01-09 01:11:55 +08:00
|
|
|
/**
|
|
|
|
|
* Default settings for QFunctions
|
|
|
|
|
*/
|
|
|
|
|
var qSettings: QSettings = _
|
|
|
|
|
|
2010-06-15 12:43:46 +08:00
|
|
|
/**
|
2010-08-10 00:42:48 +08:00
|
|
|
* Builds the CommandLineFunctions that will be used to run this script and adds them to this.functions directly or using the add() utility method.
|
2010-06-15 12:43:46 +08:00
|
|
|
*/
|
2011-04-12 04:22:44 +08:00
|
|
|
def script()
|
2010-06-15 12:43:46 +08:00
|
|
|
|
2011-08-23 22:09:51 +08:00
|
|
|
/**
|
|
|
|
|
* A default handler for the onExecutionDone() function. By default this doesn't do anything
|
|
|
|
|
*/
|
2011-08-24 04:51:54 +08:00
|
|
|
def onExecutionDone(jobs: Map[QFunction, JobRunInfo], success: Boolean) {
|
2011-08-23 22:09:51 +08:00
|
|
|
}
|
|
|
|
|
|
2010-06-15 12:43:46 +08:00
|
|
|
/**
|
2010-08-10 00:42:48 +08:00
|
|
|
* The command line functions that will be executed for this QScript.
|
2010-06-15 12:43:46 +08:00
|
|
|
*/
|
2012-01-09 01:11:55 +08:00
|
|
|
var functions = Seq.empty[QFunction]
|
2010-06-15 12:43:46 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Exchanges the extension on a file.
|
2010-10-16 01:01:36 +08:00
|
|
|
* @param file File to look for the extension.
|
|
|
|
|
* @param oldExtension Old extension to strip off, if present.
|
|
|
|
|
* @param newExtension New extension to append.
|
|
|
|
|
* @return new File with the new extension in the current directory.
|
2010-06-15 12:43:46 +08:00
|
|
|
*/
|
2010-08-10 00:42:48 +08:00
|
|
|
protected def swapExt(file: File, oldExtension: String, newExtension: String) =
|
2010-06-15 12:43:46 +08:00
|
|
|
new File(file.getName.stripSuffix(oldExtension) + newExtension)
|
|
|
|
|
|
2010-10-16 01:01:36 +08:00
|
|
|
/**
|
|
|
|
|
* Exchanges the extension on a file.
|
|
|
|
|
* @param dir New directory for the file.
|
|
|
|
|
* @param file File to look for the extension.
|
|
|
|
|
* @param oldExtension Old extension to strip off, if present.
|
|
|
|
|
* @param newExtension New extension to append.
|
|
|
|
|
* @return new File with the new extension in dir.
|
|
|
|
|
*/
|
|
|
|
|
protected def swapExt(dir: File, file: File, oldExtension: String, newExtension: String) =
|
|
|
|
|
new File(dir, file.getName.stripSuffix(oldExtension) + newExtension)
|
|
|
|
|
|
2010-06-15 12:43:46 +08:00
|
|
|
/**
|
2010-08-10 00:42:48 +08:00
|
|
|
* Adds one or more command line functions to be run.
|
2010-10-16 01:01:36 +08:00
|
|
|
* @param functions Functions to add.
|
2010-06-15 12:43:46 +08:00
|
|
|
*/
|
2012-01-09 01:11:55 +08:00
|
|
|
def add(functions: QFunction*) {
|
2010-10-16 04:00:35 +08:00
|
|
|
functions.foreach(function => function.addOrder = QScript.nextAddOrder)
|
|
|
|
|
this.functions ++= functions
|
|
|
|
|
}
|
2010-12-12 13:10:45 +08:00
|
|
|
|
2012-01-09 01:11:55 +08:00
|
|
|
def addAll(functions: Seq[QFunction]) {
|
2010-12-12 13:10:45 +08:00
|
|
|
functions.foreach( f => add(f) )
|
|
|
|
|
}
|
2012-10-16 03:03:33 +08:00
|
|
|
|
2012-10-18 07:39:03 +08:00
|
|
|
/**
|
|
|
|
|
* Convert all @Output files to remote output files.
|
|
|
|
|
* @param remoteFileConverter Converter for files to remote files.
|
|
|
|
|
*/
|
|
|
|
|
def mkRemoteOutputs(remoteFileConverter: RemoteFileConverter) {
|
|
|
|
|
for (field <- outputFields) {
|
|
|
|
|
val fieldFile = ClassFieldCache.getFieldFile(this, field)
|
|
|
|
|
if (fieldFile != null && !fieldFile.isInstanceOf[RemoteFile]) {
|
|
|
|
|
val fieldName = ClassFieldCache.fullName(field)
|
|
|
|
|
val remoteFile = remoteFileConverter.convertToRemote(fieldFile, fieldName)
|
|
|
|
|
ClassFieldCache.setFieldValue(this, field, remoteFile)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-11-30 02:31:08 +08:00
|
|
|
* Pull all remote files to the local disk
|
2012-10-18 07:39:03 +08:00
|
|
|
*/
|
2012-10-16 03:03:33 +08:00
|
|
|
def pullInputs() {
|
2012-12-05 01:32:00 +08:00
|
|
|
val inputs = ClassFieldCache.getFieldFiles(this, inputFields)
|
|
|
|
|
for (remoteFile <- filterRemoteFiles(inputs)) {
|
|
|
|
|
logger.info("Pulling %s from %s".format(remoteFile.getAbsolutePath, remoteFile.remoteDescription))
|
|
|
|
|
remoteFile.pullToLocal()
|
|
|
|
|
}
|
2012-10-16 03:03:33 +08:00
|
|
|
}
|
|
|
|
|
|
2012-10-18 07:39:03 +08:00
|
|
|
/**
|
2012-11-30 02:31:08 +08:00
|
|
|
* Push all remote files from the local disk
|
2012-10-18 07:39:03 +08:00
|
|
|
*/
|
2012-10-16 03:03:33 +08:00
|
|
|
def pushOutputs() {
|
2012-12-05 01:32:00 +08:00
|
|
|
val outputs = ClassFieldCache.getFieldFiles(this, outputFields)
|
|
|
|
|
for (remoteFile <- filterRemoteFiles(outputs)) {
|
|
|
|
|
logger.info("Pushing %s to %s".format(remoteFile.getAbsolutePath, remoteFile.remoteDescription))
|
|
|
|
|
remoteFile.pushToRemote()
|
|
|
|
|
}
|
2012-10-16 03:03:33 +08:00
|
|
|
}
|
|
|
|
|
|
2012-12-05 01:32:00 +08:00
|
|
|
private def filterRemoteFiles(fields: Seq[File]): Seq[RemoteFile] =
|
|
|
|
|
fields.filter(field => field != null && field.isInstanceOf[RemoteFile]).map(_.asInstanceOf[RemoteFile])
|
2012-10-18 07:39:03 +08:00
|
|
|
/**
|
2012-11-30 02:31:08 +08:00
|
|
|
* @return the inputs or null if there are no inputs
|
2012-10-18 07:39:03 +08:00
|
|
|
*/
|
2012-11-30 02:31:08 +08:00
|
|
|
def remoteInputs: AnyRef = null
|
2012-10-24 00:34:26 +08:00
|
|
|
|
|
|
|
|
/**
|
2012-11-30 02:31:08 +08:00
|
|
|
* @return the outputs or null if there are no outputs
|
2012-10-24 00:34:26 +08:00
|
|
|
*/
|
2012-11-30 02:31:08 +08:00
|
|
|
def remoteOutputs: AnyRef = null
|
2012-10-16 03:03:33 +08:00
|
|
|
|
2012-10-17 06:49:10 +08:00
|
|
|
/** The complete list of fields. */
|
|
|
|
|
def functionFields: Seq[ArgumentSource] = ClassFieldCache.classFunctionFields(this.getClass)
|
|
|
|
|
/** The @Input fields. */
|
|
|
|
|
def inputFields: Seq[ArgumentSource] = ClassFieldCache.classInputFields(this.getClass)
|
|
|
|
|
/** The @Output fields. */
|
|
|
|
|
def outputFields: Seq[ArgumentSource] = ClassFieldCache.classOutputFields(this.getClass)
|
|
|
|
|
/** The @Argument fields. */
|
|
|
|
|
def argumentFields: Seq[ArgumentSource] = ClassFieldCache.classArgumentFields(this.getClass)
|
2010-10-16 04:00:35 +08:00
|
|
|
}
|
2010-10-08 21:30:28 +08:00
|
|
|
|
2010-10-16 04:00:35 +08:00
|
|
|
object QScript {
|
|
|
|
|
private var addOrder = 0
|
|
|
|
|
private def nextAddOrder = {
|
|
|
|
|
addOrder += 1
|
2012-01-09 01:11:55 +08:00
|
|
|
Seq(addOrder)
|
2010-10-16 04:00:35 +08:00
|
|
|
}
|
2010-06-15 12:43:46 +08:00
|
|
|
}
|