changeset 7:19597b57ada8 draft

Uploaded
author holtgrewe
date Mon, 12 Aug 2013 09:58:57 -0400
parents 71241c4dc4d0
children 681bfc781c26
files bam2roi.ctd bam2roi.xml bed_sort.sh ctd2galaxy.py gff_sort.sh ngs_roi/app.py roi_feature_projection.ctd roi_feature_projection.xml roi_filter.sh roi_plot_9.sh roi_plot_thumbnails.ctd roi_plot_thumbnails.py roi_plot_thumbnails.xml
diffstat 11 files changed, 409 insertions(+), 212 deletions(-) [+]
line wrap: on
line diff
--- a/bam2roi.ctd	Fri Jun 28 14:01:42 2013 -0400
+++ b/bam2roi.ctd	Mon Aug 12 09:58:57 2013 -0400
@@ -1,26 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<tool>
-	<name>Bam2roi</name>
+<tool name="Bam2roi" version="0.1" docurl="http://www.seqan.de" category="" >
 	<executableName>bam2roi</executableName>
-	<version>0.1</version>
 	<description>Create ROI from BAM file.</description>
 	<manual>Calculated consecutive regions of coverage from alignment file IN.bam and write regions of interst to file OUT.roi. Counting is performed over the entire region (including intron and N-regions) based on the CIGAR string of the alignment record.
 </manual>
-	<docurl>http://www.seqan.de</docurl>
-	<category></category>
 	<cli>
+		<clielement optionIdentifier="--write-ctd-file-ext" isList="false">
+			<mapping referenceName="bam2roi.write-ctd-file-ext" />
+		</clielement>
 		<clielement optionIdentifier="--verbose" isList="false">
 			<mapping referenceName="bam2roi.verbose" />
 		</clielement>
-		<clielement optionIdentifier="--vverbose" isList="false">
-			<mapping referenceName="bam2roi.vverbose" />
+		<clielement optionIdentifier="--very-verbose" isList="false">
+			<mapping referenceName="bam2roi.very-verbose" />
 		</clielement>
 		<clielement optionIdentifier="--input-file" isList="false">
 			<mapping referenceName="bam2roi.input-file" />
 		</clielement>
+		<clielement optionIdentifier="--input-file-file-ext" isList="false">
+			<mapping referenceName="bam2roi.input-file-file-ext" />
+		</clielement>
 		<clielement optionIdentifier="--output-file" isList="false">
 			<mapping referenceName="bam2roi.output-file" />
 		</clielement>
+		<clielement optionIdentifier="--output-file-file-ext" isList="false">
+			<mapping referenceName="bam2roi.output-file-file-ext" />
+		</clielement>
 		<clielement optionIdentifier="--strand-specific" isList="false">
 			<mapping referenceName="bam2roi.strand-specific" />
 		</clielement>
@@ -31,15 +36,18 @@
 			<mapping referenceName="bam2roi.link-over-skipped" />
 		</clielement>
 	</cli>
-	<PARAMETERS  version="1.4" xsi:noNamespaceSchemaLocation="http://open-ms.sourceforge.net/schemas/Param_1_4.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+	<PARAMETERS version="1.6.2" xsi:noNamespaceSchemaLocation="http://open-ms.sourceforge.net/schemas/Param_1_6_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 		<NODE name="bam2roi" description="Create ROI from BAM file.">
-			<ITEM name="verbose" value="false" type="string" description="Verbose mode." restrictions="true,false"  />
-			<ITEM name="vverbose" value="false" type="string" description="Very verbose mode." restrictions="true,false"  />
-			<ITEM name="input-file" value="" type="string" description="SAM/BAM formatted file.  Must be sorted by coordinate." tags="input file,required" supported_formats="*sam,*bam"  />
-			<ITEM name="output-file" value="" type="string" description="Output file with regions of interest." tags="output file,required" supported_formats="*roi"  />
-			<ITEM name="strand-specific" value="false" type="string" description="Calculate strand-specific ROIs (see section Strand Specificness below." restrictions="true,false"  />
-			<ITEM name="ignore-pairing" value="false" type="string" description="Ignore paired information.  Also see Section ROI Creation Details." restrictions="true,false"  />
-			<ITEM name="link-over-skipped" value="false" type="string" description="Link over skipped bases in the read alignment." restrictions="true,false"  />
+			<ITEM name="write-ctd-file-ext" value="" type="string" description="Override file extension for --write-ctd" required="false" advanced="true" />
+			<ITEM name="verbose" value="false" type="string" description="Verbose mode." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="very-verbose" value="false" type="string" description="Very verbose mode." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="input-file" value="" type="input-file" description="SAM/BAM formatted file.  Must be sorted by coordinate." supported_formats="*.sam,*.bam" required="true" advanced="false" />
+			<ITEM name="input-file-file-ext" value="" type="string" description="Override file extension for --input-file" restrictions="sam,bam" required="false" advanced="true" />
+			<ITEM name="output-file" value="" type="output-file" description="Output file with regions of interest." supported_formats="*.roi" required="true" advanced="false" />
+			<ITEM name="output-file-file-ext" value="" type="string" description="Override file extension for --output-file" restrictions="roi" required="false" advanced="true" />
+			<ITEM name="strand-specific" value="false" type="string" description="Calculate strand-specific ROIs (see section Strand Specificness below." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="ignore-pairing" value="false" type="string" description="Ignore paired information.  Also see Section ROI Creation Details." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="link-over-skipped" value="false" type="string" description="Link over skipped bases in the read alignment." restrictions="true,false" required="false" advanced="false" />
 		</NODE>
 	</PARAMETERS>
 </tool>
--- a/bam2roi.xml	Fri Jun 28 14:01:42 2013 -0400
+++ b/bam2roi.xml	Mon Aug 12 09:58:57 2013 -0400
@@ -1,77 +1,33 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<tool id="bam2roi" name="BAM to ROI">
-    <command>
-    <!-- First, create link for the input file -->
-    ln -s ${bam2roi_input_file} ${bam2roi_input_file}.${bam2roi_input_file.ext};
-    touch ${bam2roi_output_file};
-    ln -s ${bam2roi_output_file} ${bam2roi_output_file}.${bam2roi_output_file.ext};
-    
-    <!-- Call bam2roi -->
-    bam2roi
-    $bam2roi_verbosity
+<tool id="bam2roi" name="Bam2roi">
+    <command>bam2roi
+    $bam2roi_verbose
+    $bam2roi_very_verbose
+    --input-file "$bam2roi_input_file"
+    --output-file "$bam2roi_output_file"
     $bam2roi_strand_specific
     $bam2roi_ignore_pairing
     $bam2roi_link_over_skipped
-    --input-file $bam2roi_input_file.${bam2roi_input_file.ext}
-    --output-file $bam2roi_output_file.${bam2roi_output_file.ext};
-
-    <!-- Get rid of links again -->
-    rm -f ${bam2roi_input_file}.${bam2roi_input_file.ext};
-    rm -f ${bam2roi_output_file}.${bam2roi_output_file.ext};
-    </command>
-
+    #if $bam2roi_input_file
+        --input-file-file-ext ${bam2roi_input_file.ext}
+    #end if
+    #if $bam2roi_output_file
+        --output-file-file-ext ${bam2roi_output_file.ext}
+    #end if</command>
     <description>Create ROI from BAM file.</description>
-    
-    <!--
-      Input Files and Parameters
-    -->
     <inputs>
-        <param name="bam2roi_input_file" type="data" format="sam,bam"
-               label="Input File"
-               help="SAM/BAM formatted file.  Must be sorted by coordinate." />
-
-        <param name="bam2roi_ignore_pairing" type="boolean" falsevalue="" truevalue="--ignore-pairing"
-               label="Ignore paired information"
-               help="By default, a whole fragment/template extends a ROI for paired-end data.  When selected, reads are treated as in the single-end case." />
-        <param name="bam2roi_link_over_skipped" type="boolean" falsevalue="" truevalue="--link-over-skipped"
-               label="Link over skipped bases"
-               help="When selected, a ROI continues over skipped bases." />
-        <param name="bam2roi_strand_specific" type="boolean" falsevalue="" truevalue="--strand-specific"
-               label="Compute strand-specific ROIs"
-               help="When selected, the strands of the reads alignments are considered, e.g. there can be two or more ROIs on different strands that would overlap on the same strand." />
-
-        <param name="bam2roi_verbosity" type="select" label="Verbosity" force_select="true">
-            <option value="" selected="true">normal</option>
-            <option value="--verbose">verbose</option>
-            <option value="--very-verbose">very verbose</option>
-        </param>
+        <param falsevalue="" truevalue="--verbose" type="boolean" name="bam2roi_verbose" label="Verbose mode." />
+        <param falsevalue="" truevalue="--very-verbose" type="boolean" name="bam2roi_very_verbose" label="Very verbose mode." />
+        <param falsevalue="" truevalue="--link-over-skipped" type="boolean" name="bam2roi_link_over_skipped" label="Link over skipped bases in the read alignment." />
+        <param falsevalue="" truevalue="--ignore-pairing" type="boolean" name="bam2roi_ignore_pairing" label="Ignore paired information.  Also see Section ROI Creation Details." />
+        <param label="SAM/BAM formatted file.  Must be sorted by coordinate." type="data" name="bam2roi_input_file" format="sam,bam" />
+        <param falsevalue="" truevalue="--strand-specific" type="boolean" name="bam2roi_strand_specific" label="Calculate strand-specific ROIs (see section Strand Specificness below." />
     </inputs>
-    
-    <!--
-      Output Files
-    -->
     <outputs>
-        <data label="${bam2roi_input_file.name}.roi" name="bam2roi_output_file" format="roi" />
+        <data label="Output file with regions of interest." name="bam2roi_output_file" format="roi" />
     </outputs>
-
-    <!--
-      Recognize errors by return code and not output to stderr.
-    -->
     <stdio>
         <exit_code range="1:" level="fatal" />
         <exit_code range=":-1" level="fatal" />
     </stdio>
-
-    <!--
-      Tool Help
-    -->
-    <help>No help yet.</help>
-
-    <!--
-      Dependencies
-    -->
-    <requirements>
-        <requirement type="binary">bam2roi</requirement>
-        <requirement type="python-module">Cheetah</requirement>
-    </requirements>
 </tool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bed_sort.sh	Mon Aug 12 09:58:57 2013 -0400
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# Sorting of BED files.
+#
+# USAGE: sort_bed.sh [OPTIONS] -i IN.roi -o OUT.roi
+#
+# Options:
+#   -r     reverse orientation
+#   -p     sort by position (ref, start, end) -- default
+
+# The parameters that we will pass to sort.
+SORT_POS_ARGS="-k 1,1 -k 2,2n -k 3,3n"
+SORT_POS_ARGS_REV="-k 1,1r -k 2,2nr -k 3,3nr"
+
+# The arguments will go here.
+SORT_BY=beginPos
+REVERSE=
+
+# Parse option values.
+while getopts "pc:i:o:n:r" opt; do
+    case $opt in
+        i)
+            IN_FILE=$OPTARG
+            ;;
+        o)
+            OUT_FILE=$OPTARG
+            ;;
+        r)
+            REVERSE=r
+            ;;
+        \?)
+            echo "Invalid option: -$OPTARG" >&2
+            exit 1
+            ;;
+    esac
+done
+
+# Check that -i or -o are given.
+if [[ "$IN_FILE" == "" || "$OUT_FILE" == "" ]]; then
+    echo "Missing option -i or -o" >&2
+    exit 1
+fi
+
+# Setup sort args.
+case $SORT_BY in
+    beginPos)
+        if [[ "$REVERSE" == "r" ]]; then
+            SORT_ARGS=${SORT_POS_ARGS_REV}
+        else
+            SORT_ARGS=${SORT_POS_ARGS}
+        fi
+        ;;
+esac
+
+# Execute sorting.
+#echo "OUT_FILE=${OUT_FILE}" 2>&2
+#echo "SORT_ARGS=${SORT_ARGS}" 1>&2
+(
+    export LC_ALL=C
+    #echo "sort ${SORT_ARGS} <(grep -v '^#' ${IN_FILE});" 1>&2
+    sort ${SORT_ARGS} <(grep -v '^#' ${IN_FILE});
+) > ${OUT_FILE}
+
+exit $?
--- a/ctd2galaxy.py	Fri Jun 28 14:01:42 2013 -0400
+++ b/ctd2galaxy.py	Mon Aug 12 09:58:57 2013 -0400
@@ -5,6 +5,10 @@
 only used here at the moment.
 """
 
+# TODO(holtgrew): Option lists do not work at the moment.
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>'
+
 try:
     import argparse
 except ImportError:
@@ -14,6 +18,12 @@
 import xml.sax
 import xml.sax.saxutils
 
+
+# The suffix to identify file extension options (for '--arg-${NO}${SUFFIX}'
+# and '--${PARAM_NAME}${SUFFIX}').
+FILE_EXT_SUFFIX = '-file-ext'
+
+
 class CTDFormatException(Exception):
     """Raised when there is a format error in CTD."""
     
@@ -59,10 +69,12 @@
     :ivar children: children of the node
     :type children: dict with name to node mapping
     :ivar cli_element: CLIElement that this parameter is mapped to.
+    :ivar required: Whether or not this parameter is required.
+    :type required: bool
     """
     
     def __init__(self, kind='', name='', description='', value='', type_='', tags='',
-                 restrictions='', supported_formats=''):
+                 restrictions='', supported_formats='', required=False):
         """Initialize the object."""
         self.kind = kind
         self.name = name
@@ -76,6 +88,7 @@
         self.parent = None  # not set, usually a list
         self.children = {}
         self.cli_element = None
+        self.required = required
 
     def computePath(self, is_root=True, path=[]):
         """Compute path entry from parent links.
@@ -110,8 +123,8 @@
     def __str__(self):
         """Return string representation."""
         t = (self.name, self.description, self.value, self.type_, self.tags,
-             self.supported_formats, self.children, self.path)
-        return 'ParametersNode(%s, %s, %s, %s, %s, %s, %s, path=%s)' % tuple(map(repr, t))
+             self.supported_formats, self.children, self.path, self.required)
+        return 'ParametersNode(%s, %s, %s, %s, %s, %s, %s, path=%s, %s)' % tuple(map(repr, t))
 
     def __repr__(self):
         """Return programmatic representation, same as __str__()."""
@@ -194,13 +207,16 @@
             # Create the top level Tool object.
             self.tool = Tool()
             self.result = self.tool
+            if not attrs.get('name'):
+                raise CTDFormatException('No attribute "name" in <tool> tag.')
+            self.tool.name = attrs.get('name')
         elif self.stack == ['tool', 'cli', 'clielement']:
             # Create a new CLIElement object for a <clieelement> tag.
             if not attrs.get('isList'):
                 raise CTDFormatException('No attribute isList in <clielement>.')
             if attrs.get('optionIdentifier') is None:
                 raise CTDFormatException('no attribute optionIdentifier in <clielement>.')
-            is_list = (attrs.get('isList') == 'false')
+            is_list = (attrs.get('isList') == 'true')
             option_identifier = attrs.get('optionIdentifier')
             self.tool.cli_elements.append(CLIElement(option_identifier=option_identifier, is_list=is_list))
         elif self.stack == ['tool', 'cli', 'clielement', 'mapping']:
@@ -221,19 +237,21 @@
             node.parent = self.parameter_node
             self.parameter_node.children[name] = node
             self.parameter_node = node
-        elif self.stack[:2] == ['tool', 'PARAMETERS'] and self.stack[-1] == 'ITEM':
-            # Create a new item ParametersNode for the <ITEM> entry.
+        elif self.stack[:2] == ['tool', 'PARAMETERS'] and self.stack[-1] in ['ITEM', 'ITEMLIST']:
+            # Create a new item ParametersNode for the <ITEM>/<ITEMLIST> entry.
             if not attrs.get('name'):
-                raise CTDFormatException('no attribute name in <ITEM>')
+                raise CTDFormatException('no attribute name in <ITEM>/<ITEMLIST>')
             name = attrs.get('name')
             value = attrs.get('value')
             type_ = attrs.get('type')
             tags = attrs.get('tags')
             description = attrs.get('description')
             restrictions = attrs.get('restrictions')
-            supported_formats = attrs.get('supported_formats')
+            required = attrs.get('required') == 'true'
+            supported_formats = attrs.get('supported_formats', '')
+            kind = {'ITEM': 'item', 'ITEMLIST': 'itemlist'}[self.stack[-1]]
             child = ParametersNode(
-                kind='item', name=name, description=description, value=value,
+                kind=kind, name=name, description=description, value=value,
                 type_=type_, tags=tags, supported_formats=supported_formats,
                 restrictions=restrictions)
             self.parameter_node.children[name] = child
@@ -248,9 +266,7 @@
 
     def characters(self, content):
         """Handle characters in XML file."""
-        if self.stack == ['tool', 'name']:
-            self.tool.name += content
-        elif self.stack == ['tool', 'executableName']:
+        if self.stack == ['tool', 'executableName']:
             self.tool.executable_name += content
         elif self.stack == ['tool', 'version']:
             self.tool.version += content
@@ -299,7 +315,7 @@
     def appendTag(self, tag, text='', args={}):
         """Append a tag to self.result with text content only or no content at all."""
         e = xml.sax.saxutils.quoteattr
-        args_str = ' '.join('%s=%s' % (key, e(str(value))) for key, value in args.items())
+        args_str = ' '.join('%s=%s' % (key, e(str(value))) for key, value in args.items() if value is not None)
         if args_str:
             args_str = ' '+ args_str
         vals = {'indent': self.indent(),
@@ -330,14 +346,14 @@
     def handleParameters(self, node):
         """Recursion for appending tags for ParametersNode."""
         for pn in node.children.values():
-            if pn.kind == 'item':
+            if pn.kind in ['item', 'itemlist']:
                 args = {'name': pn.name,
                         'value': pn.value,
                         'type': pn.type_,
                         'description': pn.description,
                         'restrictions': pn.restrictions,
                         'tags': pn.tags}
-                self.appendTag('ITEM', args=args)
+                self.appendTag(pn.kind.upper(), args=args)
             else:  # node.kind == 'node'
                 args = {'name': pn.name,
                         'description': pn.description}
@@ -375,7 +391,7 @@
             self.closeTag('clielement')
         self.indent_level -= 1
         self.closeTag('cli')
-        # <PARAMETERS>, <NODE>, <ITEM> group
+        # <PARAMETERS>, <NODE>, <ITEM>, <ITEMLIST> group
         self.openTag('PARAMETERS', args={'version': 1.4,
                                          'xsi:noNamespaceSchemaLocation': 'http://open-ms.sourceforge.net/schemas/Param_1_4.xsd',
                                          'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'})
@@ -390,6 +406,34 @@
             f.write(x)
 
 
+class GalaxyCommandSnippet(object):
+    """Stores a snippet for the Galaxy <command> tag.
+
+    Such a snippet consists of a list of text that will be concatenated using
+    space as the separator.
+
+    Optionally, a condition can be given which will be pasted verbatimly into
+    an #if condition that will also be properly closed.  As a bonus, the
+    snippet will be properly indented.
+    """
+
+    def __init__(self, words, condition=None, indent=4, level=1):
+        self.words = words
+        self.condition = condition
+        self.indent = indent
+        self.level = level
+
+    def build(self):
+        res = []
+        if self.condition:
+            res.append('#if %s' % self.condition)
+        res.append(' '.join(self.words))
+        if self.condition:
+            res[-1] = ' ' * self.indent + res[-1]
+            res.append('#end if')
+        return '\n'.join([' ' * self.indent * self.level + l for l in res])
+
+
 class GalaxyWriter(XMLWriter):
     """Write a Tool to the Galaxy format."""
 
@@ -424,12 +468,16 @@
 
     def addInputParam(self, param_node):
         """Add a ParametersNode object if it is to go to <inputs>."""
-        if param_node.tags and 'output file' in param_node.tags.split(','):
+        if param_node.type_ == 'output-file':
             return  # Skip output files
-        if param_node.kind != 'item':
+        if param_node.kind not in ['item', 'itemlist']:
             return  # Skip if not item.
+        if param_node.name.endswith('-file-ext'):
+            return  # Skip if extension to override.
         args = {}
-        if param_node.tags and 'input file' in param_node.tags.split(','):
+        if param_node.tags and 'required' not in param_node.tags.split(','):
+            args['optional'] = 'true'  # false would be default
+        if param_node.type_ == 'input-file':
             args['type'] = 'data'
             args['format'] = ','.join([x.replace('*', '').replace('.', '')
                                        for x in param_node.supported_formats.split(',')])
@@ -469,10 +517,12 @@
             
     def addOutputParam(self, param_node):
         """Add a ParametersNode object if it is to go to <inputs>."""
-        if not param_node.tags or not 'output file' in param_node.tags.split(','):
+        if param_node.type_ != 'output-file':
             return  # Only add for output files.
+        if param_node.name.endswith('-file-ext'):
+            return  # Skip if extension to override.
         args = {}
-        if '.'  in param_node.supported_formats:
+        if '.' in param_node.supported_formats:
             args['format'] = param_node.supported_formats.split(',')[0].split('.')[-1]
         else:
             args['format'] = param_node.supported_formats.split(',')[0].split('*')[-1]
@@ -482,18 +532,44 @@
             
     def addCommandTag(self, tool):
         """Write <command> tag to self.result."""
-        lst = []
+        file_ext_elements = []
+        # Process non-file-extension arguments.
+        snippets = []
         for ce in tool.cli_elements:
+            if ce.param_node.name.endswith('-file-ext'):
+                file_ext_elements.append(ce)
+                continue  # Skip -file-ext options.
+            # The name of the variable that is used.
+            var_name = '$' + ce.mapping_path.replace('-', '_').replace('.', '_')
+            # Check whether it is optional.
+            optional = bool(ce.param_node.tags and 'required' not in ce.param_node.tags.split(','))
+            # Check whether it is a boolean.
             bool_param = False
             if ce.param_node.type_ == 'string' and ce.param_node.restrictions and \
                sorted(ce.param_node.restrictions.split(',')) == ['false', 'true']:
                 bool_param = True
-            if not bool_param and ce.option_identifier:
-                lst.append(ce.option_identifier)
-            # The path  mapping is not ideal but should work OK.
-            lst.append('$' + ce.mapping_path.replace('-', '_').replace('.', '_'))
-        txt = [tool.executable_name] + lst
-        self.appendTag('command', text=' '.join(txt))
+            # Get variable name.
+            val = '"' + var_name + '"'
+            # Build the snippet for the command.
+            if bool_param:
+                # The true value for boolean parameters is the argument itself.
+                snippets.append(GalaxyCommandSnippet([var_name]))
+            else:
+                condition = {True: var_name, False: None}.get(optional)
+                snippets.append(GalaxyCommandSnippet([ce.option_identifier, val],
+                                                     condition=condition))
+        # Process file extension arguments.
+        ext_overrides = []
+        for ce in file_ext_elements:
+            if ce.option_identifier == '--write-ctd-file-ext':
+                continue  # Skip special args.
+            # The name of the variable that is used.
+            var_name = ce.mapping_path[:-len('-file-ext')].replace('-', '_').replace('.', '_')
+            snippets.append(GalaxyCommandSnippet([ce.option_identifier, '${%s.ext}' % var_name],
+                                                 condition='$%s' % var_name))
+        # Finalize building the command line.
+        txt = GalaxyCommandSnippet([tool.executable_name]).build() + '\n' + '\n'.join([s.build() for s in snippets])
+        self.appendTag('command', text=txt)
 
 
 def main():
--- a/gff_sort.sh	Fri Jun 28 14:01:42 2013 -0400
+++ b/gff_sort.sh	Mon Aug 12 09:58:57 2013 -0400
@@ -9,8 +9,8 @@
 #   -p     sort by position (ref, start, end) -- default
 
 # The parameters that we will pass to sort.
-SORT_POS_ARGS="-k 1,1 -k 2,2n -k 3,3n"
-SORT_POS_ARGS_REV="-k 1,1r -k 2,2nr -k 3,3nr"
+SORT_POS_ARGS="-k 1,1 -k 4,4n -k 5,5n"
+SORT_POS_ARGS_REV="-k 1,1r -k 4,4nr -k 5,5nr"
 
 # The arguments will go here.
 SORT_BY=beginPos
--- a/ngs_roi/app.py	Fri Jun 28 14:01:42 2013 -0400
+++ b/ngs_roi/app.py	Mon Aug 12 09:58:57 2013 -0400
@@ -44,16 +44,9 @@
     def __init__(self, args):
         self.args = args
 
-    def _mkLinks(self):
-        """Create symlink."""
-        subprocess.call(['ln', '-s', self.args.in_file, self.args.in_file + '.roi'])
-
-    def _rmLinks(self):
-        """Remove symlink."""
-        subprocess.call(['rm', '-f', self.args.in_file + '.roi'])
-
     def run(self):
-        cmd_args = ['-if', self.args.in_file + '.roi',
+        cmd_args = ['-if', self.args.in_file,
+                    '--in-file-ext', 'roi',
                     '-o', os.path.join(self.args.out_dir, 'thumbnail_'),
                     '--max-rois', self.args.max_rois,
                     '--max-value', self.args.max_value,
@@ -67,10 +60,8 @@
         #import pdb; pdb.set_trace()
         import sys
         print >>sys.stderr, 'Running %s' % ' '.join(cmd_args)
-        self._mkLinks()
         p = subprocess.Popen(cmd_args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
         res = p.wait()
-        self._rmLinks()
         if res:
             print 'ERROR', p.stdin, p.stderr
         return res
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/roi_feature_projection.ctd	Mon Aug 12 09:58:57 2013 -0400
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tool name="RoiFeatureProjection" version="0.1" docurl="http://www.seqan.de" category="NGS ROI Analysis" >
+	<executableName>roi_feature_projection</executableName>
+	<description>Region Of Interest Projection.</description>
+	<manual>Compute the projection of a ROI file to regions from a BED or GFF file.  The result is a ROI file where each interval from the BED/GFF/GTF file that overlapped with one input ROI file is a region of interest, with the coverage counts projected to the new region of interest.
+</manual>
+	<cli>
+		<clielement optionIdentifier="--write-ctd-file-ext" isList="false">
+			<mapping referenceName="roi_feature_projection.write-ctd-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--quiet" isList="false">
+			<mapping referenceName="roi_feature_projection.quiet" />
+		</clielement>
+		<clielement optionIdentifier="--verbose" isList="false">
+			<mapping referenceName="roi_feature_projection.verbose" />
+		</clielement>
+		<clielement optionIdentifier="--very-verbose" isList="false">
+			<mapping referenceName="roi_feature_projection.very-verbose" />
+		</clielement>
+		<clielement optionIdentifier="--in-roi" isList="false">
+			<mapping referenceName="roi_feature_projection.in-roi" />
+		</clielement>
+		<clielement optionIdentifier="--in-roi-file-ext" isList="false">
+			<mapping referenceName="roi_feature_projection.in-roi-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--in-features" isList="false">
+			<mapping referenceName="roi_feature_projection.in-features" />
+		</clielement>
+		<clielement optionIdentifier="--in-features-file-ext" isList="false">
+			<mapping referenceName="roi_feature_projection.in-features-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--out-roi" isList="false">
+			<mapping referenceName="roi_feature_projection.out-roi" />
+		</clielement>
+		<clielement optionIdentifier="--out-roi-file-ext" isList="false">
+			<mapping referenceName="roi_feature_projection.out-roi-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--genome" isList="false">
+			<mapping referenceName="roi_feature_projection.genome" />
+		</clielement>
+		<clielement optionIdentifier="--genome-file-ext" isList="false">
+			<mapping referenceName="roi_feature_projection.genome-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--mode" isList="false">
+			<mapping referenceName="roi_feature_projection.mode" />
+		</clielement>
+		<clielement optionIdentifier="--strand-specific" isList="false">
+			<mapping referenceName="roi_feature_projection.strand-specific" />
+		</clielement>
+		<clielement optionIdentifier="--gff-type" isList="false">
+			<mapping referenceName="roi_feature_projection.gff-type" />
+		</clielement>
+		<clielement optionIdentifier="--gff-group-by" isList="false">
+			<mapping referenceName="roi_feature_projection.gff-group-by" />
+		</clielement>
+	</cli>
+	<PARAMETERS version="1.6.2" xsi:noNamespaceSchemaLocation="http://open-ms.sourceforge.net/schemas/Param_1_6_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+		<NODE name="roi_feature_projection" description="Region Of Interest Projection.">
+			<ITEM name="write-ctd-file-ext" value="" type="string" description="Override file extension for --write-ctd" required="false" advanced="true" />
+			<ITEM name="quiet" value="false" type="string" description="Set verbosity to a minimum." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="verbose" value="false" type="string" description="Enable verbose output." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="very-verbose" value="false" type="string" description="Enable very verbose output." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="in-roi" value="" type="input-file" description="ROI file to read." supported_formats="*.roi" required="true" advanced="false" />
+			<ITEM name="in-roi-file-ext" value="" type="string" description="Override file extension for --in-roi" restrictions="roi" required="false" advanced="true" />
+			<ITEM name="in-features" value="" type="input-file" description="BED, GFF, or GTF file to read." supported_formats="*.bed,*.gff,*.gtf" required="true" advanced="false" />
+			<ITEM name="in-features-file-ext" value="" type="string" description="Override file extension for --in-features" restrictions="bed,gff,gtf" required="false" advanced="true" />
+			<ITEM name="out-roi" value="" type="output-file" description="ROI file to write." supported_formats="*.roi" required="true" advanced="false" />
+			<ITEM name="out-roi-file-ext" value="" type="string" description="Override file extension for --out-roi" restrictions="roi" required="false" advanced="true" />
+			<ITEM name="genome" value="" type="input-file" description="Path to FASTA file with genome; optional.  When given, this is used for computing the overall region&apos;s C+G content." supported_formats="*.fasta,*.fa" required="false" advanced="false" />
+			<ITEM name="genome-file-ext" value="" type="string" description="Override file extension for --genome" restrictions="fasta,fa" required="false" advanced="true" />
+			<ITEM name="mode" value="projection" type="string" description="The mode in which to combine the ROI and BED/GFF file.  See section Combination Modes below for details." restrictions="intersection,projection,union,difference" required="false" advanced="false" />
+			<ITEM name="strand-specific" value="false" type="string" description="Enable strand-specific mode if set." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="gff-type" value="" type="string" description="The GFF/GTF record type (value of third column) to keep.  Keep all if not set or input file type is not GFF/GTF." required="false" advanced="false" />
+			<ITEM name="gff-group-by" value="" type="string" description="The GFF/GTF tag to use for grouping, e.g. &quot;Parent&quot;, &quot;transcript_id&quot;. No grouping if empty.  When using the grouping feature, the --mode is automatically set to projection." required="false" advanced="false" />
+		</NODE>
+	</PARAMETERS>
+</tool>
--- a/roi_feature_projection.xml	Fri Jun 28 14:01:42 2013 -0400
+++ b/roi_feature_projection.xml	Mon Aug 12 09:58:57 2013 -0400
@@ -1,87 +1,52 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<tool id="roi_feature_projection" name="ROI Feature Projection">
-    <description>Intersect ROIs with GFF/BED</description>
-
-    <command>
-    <!-- First, create link for the input files -->
-    #if $roi_intersect_genome# ln -s ${roi_intersect_genome} ${roi_intersect_genome}.${roi_intersect_genome.ext}; #end if
-    #if $roi_intersect_in_roi# ln -s ${roi_intersect_in_roi} ${roi_intersect_in_roi}.${roi_intersect_in_roi.ext}; #end if
-    #if $roi_intersect_out_roi# touch ${roi_intersect_out_roi}; ln -s ${roi_intersect_out_roi} ${roi_intersect_out_roi}.roi; #end if
-    #if $roi_intersect_in_features # ln -s ${roi_intersect_in_features} ${roi_intersect_in_features}.${roi_intersect_in_features.ext}; #end if
-
-    <!-- Call the feature projection on the links -->
-    roi_feature_projection $roi_intersect_strand_specific
-    --in-roi ${roi_intersect_in_roi}.${roi_intersect_in_roi.ext}
-    --in-features ${roi_intersect_in_features}.${roi_intersect_in_features.ext}
-    --out-roi ${roi_intersect_out_roi}.roi
-    --mode $roi_intersect_mode
-    #if $roi_intersect_genome#        --genome ${roi_intersect_genome}.${roi_intersect_genome.ext} #end if
-    #if $verbosity #                  $verbosity #end if
-    #if $roi_intersect_gff_type #    --gff-type $roi_intersect_gff_type #end if
-    #if $roi_intersect_gff_group_by# --gff-group-by $roi_intersect_gff_group_by #end if
-    ;
-
-    <!-- Get rid of the links again -->
-    #if $roi_intersect_genome# rm -f ${roi_intersect_genome}.${roi_intersect_genome.ext}; #end if
-    #if $roi_intersect_in_roi# rm -f ${roi_intersect_in_roi}.${roi_intersect_in_roi.ext}; #end if
-    #if $roi_intersect_in_roi# rm -f ${roi_intersect_out_roi}.roi; #end if
-    #if $roi_intersect_in_features# rm -f ${roi_intersect_in_features}.${roi_intersect_in_features.ext}; #end if
-    </command>
-
-    <!--
-      Input Files and Parameters
-    -->
+<tool id="roi_feature_projection" name="RoiFeatureProjection">
+    <command>roi_feature_projection
+    $roi_feature_projection_quiet
+    $roi_feature_projection_verbose
+    $roi_feature_projection_very_verbose
+    --in-roi "$roi_feature_projection_in_roi"
+    --in-features "$roi_feature_projection_in_features"
+    --out-roi "$roi_feature_projection_out_roi"
+    --genome "$roi_feature_projection_genome"
+    --mode "$roi_feature_projection_mode"
+    $roi_feature_projection_strand_specific
+    --gff-type "$roi_feature_projection_gff_type"
+    --gff-group-by "$roi_feature_projection_gff_group_by"
+    #if $roi_feature_projection_in_roi
+        --in-roi-file-ext ${roi_feature_projection_in_roi.ext}
+    #end if
+    #if $roi_feature_projection_in_features
+        --in-features-file-ext ${roi_feature_projection_in_features.ext}
+    #end if
+    #if $roi_feature_projection_out_roi
+        --out-roi-file-ext ${roi_feature_projection_out_roi.ext}
+    #end if
+    #if $roi_feature_projection_genome
+        --genome-file-ext ${roi_feature_projection_genome.ext}
+    #end if</command>
+    <description>Region Of Interest Projection.</description>
     <inputs>
-        <param label="BED, GFF, or GTF file to read." type="data" name="roi_intersect_in_features" format="bed,gff,gtf" />
-        <param label="ROI file to read." type="data" name="roi_intersect_in_roi" format="roi" />
-        <param label="Path to FASTA file with genome; optional.  When given, this is used for computing the overall region's C+G content." type="data" name="roi_intersect_genome" format="fasta,fa" optional="true" />
-
-        <param type="select" name="verbosity">
-          <option value="--quiet">verbose</option>
-          <option value="" selected="true">normal</option>
-          <option value="--verbose">verbose</option>
-          <option value="--very-verbose">very verbose</option>
-        </param>
-
-        <param type="text" name="roi_intersect_gff_type" value="" label="The GFF/GTF record type (value of third column) to keep.  Keep all if not set or input file type is not GFF/GTF." />
-        <param type="text" name="roi_intersect_gff_group_by" value="" label='The GFF/GTF tag to use for grouping, e.g. "Parent", "transcript_id". No grouping if empty.  When using the grouping feature, the --mode is automatically set to projection.' />
-        <param falsevalue="" truevalue="--strand-specific" type="boolean" name="roi_intersect_strand_specific" label="Enable strand-specific mode if set." />
-
-        <param type="select" name="roi_intersect_mode" value="projection" label="The mode in which to combine the ROI and BED/GFF file.  See section Combination Modes below for details.">
-            <option value="projection" selected="true">projection</option>
+        <param label="BED, GFF, or GTF file to read." type="data" name="roi_feature_projection_in_features" format="bed,gff,gtf" />
+        <param type="text" name="roi_feature_projection_gff_type" value="" label="The GFF/GTF record type (value of third column) to keep.  Keep all if not set or input file type is not GFF/GTF." />
+        <param falsevalue="" truevalue="--verbose" type="boolean" name="roi_feature_projection_verbose" label="Enable verbose output." />
+        <param label="ROI file to read." type="data" name="roi_feature_projection_in_roi" format="roi" />
+        <param falsevalue="" truevalue="--strand-specific" type="boolean" name="roi_feature_projection_strand_specific" label="Enable strand-specific mode if set." />
+        <param falsevalue="" truevalue="--very-verbose" type="boolean" name="roi_feature_projection_very_verbose" label="Enable very verbose output." />
+        <param falsevalue="" truevalue="--quiet" type="boolean" name="roi_feature_projection_quiet" label="Set verbosity to a minimum." />
+        <param label="Path to FASTA file with genome; optional.  When given, this is used for computing the overall region's C+G content." type="data" name="roi_feature_projection_genome" format="fasta,fa" />
+        <param type="text" name="roi_feature_projection_gff_group_by" value="" label='The GFF/GTF tag to use for grouping, e.g. "Parent", "transcript_id". No grouping if empty.  When using the grouping feature, the --mode is automatically set to projection.' />
+        <param type="select" name="roi_feature_projection_mode" value="projection" label="The mode in which to combine the ROI and BED/GFF file.  See section Combination Modes below for details.">
             <option value="intersection">intersection</option>
+            <option value="projection">projection</option>
             <option value="union">union</option>
             <option value="difference">difference</option>
         </param>
     </inputs>
-
-    <!--
-      Recognize errors by return code and not output to stderr.
-    -->
-
     <outputs>
-        <data label="${roi_intersect_in_roi} &amp; ${roi_intersect_in_features}"
-              name="roi_intersect_out_roi" format="roi" />
+        <data label="ROI file to write." name="roi_feature_projection_out_roi" format="roi" />
     </outputs>
- 
-    <!--
-      Recognize errors by return code and not output to stderr.
-    -->
     <stdio>
         <exit_code range="1:" level="fatal" />
         <exit_code range=":-1" level="fatal" />
     </stdio>
-
-    <!--
-      Tool Help
-    -->
-    <help>No help yet.</help>
-
-    <!--
-      Dependencies
-    -->
-    <requirements>
-        <requirement type="python-module">Cheetah</requirement>
-        <requirement type="binary">roi_feature_projection</requirement>
-    </requirements>
 </tool>
--- a/roi_plot_9.sh	Fri Jun 28 14:01:42 2013 -0400
+++ b/roi_plot_9.sh	Mon Aug 12 09:58:57 2013 -0400
@@ -13,6 +13,9 @@
 SORT_COL=0
 REVERSE=
 
+# Current directory.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
 helpme () {
    echo "host: ${HOST}"
    echo "Plot ROIs 9 per page to PDF with links to IGV."
@@ -51,10 +54,10 @@
 fi
 
    gawk -v fileName=${IN_FILE}.tmp.ps \
-        -f plot.awk \
+        -f ${DIR}/plot.awk \
         ${USED_INFILE} |gnuplot  2> /dev/null
    gawk -v roiFile=${USED_INFILE} \
-        -f ps2pswLinks.gawk \
+        -f ${DIR}/ps2pswLinks.gawk \
         ${IN_FILE}.tmp.ps > ${IN_FILE}.tmp.ln.ps
    ps2pdf ${IN_FILE}.tmp.ln.ps ${OUT_FILE}
 #   rm ${IN_FILE}.tmp.ps
@@ -62,3 +65,5 @@
 if [ "x${IN_FILE##*.}" == "xgz" ]; then
    echo rm $USED_INFILE
 fi
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/roi_plot_thumbnails.ctd	Mon Aug 12 09:58:57 2013 -0400
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tool name="RoiPlotThumbnails" version="0.1" docurl="http://www.seqan.de" category="NGS ROI Analysis" >
+	<executableName>roi_plot_thumbnails</executableName>
+	<description>Create plot grids for ROI file.</description>
+	<manual>Create PNG images with plot grids to OUT${i}.png from ROI records in IN.roi.
+</manual>
+	<cli>
+		<clielement optionIdentifier="--write-ctd-file-ext" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.write-ctd-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--verbose" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.verbose" />
+		</clielement>
+		<clielement optionIdentifier="--vverbose" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.vverbose" />
+		</clielement>
+		<clielement optionIdentifier="--input-file" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.input-file" />
+		</clielement>
+		<clielement optionIdentifier="--input-file-file-ext" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.input-file-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--output-prefix" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.output-prefix" />
+		</clielement>
+		<clielement optionIdentifier="--output-prefix-file-ext" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.output-prefix-file-ext" />
+		</clielement>
+		<clielement optionIdentifier="--max-rois" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.max-rois" />
+		</clielement>
+		<clielement optionIdentifier="--max-value" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.max-value" />
+		</clielement>
+		<clielement optionIdentifier="--num-cols" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.num-cols" />
+		</clielement>
+		<clielement optionIdentifier="--num-rows" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.num-rows" />
+		</clielement>
+		<clielement optionIdentifier="--plot-height" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.plot-height" />
+		</clielement>
+		<clielement optionIdentifier="--plot-width" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.plot-width" />
+		</clielement>
+		<clielement optionIdentifier="--border-width" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.border-width" />
+		</clielement>
+		<clielement optionIdentifier="--spacing" isList="false">
+			<mapping referenceName="roi_plot_thumbnails.spacing" />
+		</clielement>
+	</cli>
+	<PARAMETERS version="1.6.2" xsi:noNamespaceSchemaLocation="http://open-ms.sourceforge.net/schemas/Param_1_6_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+		<NODE name="roi_plot_thumbnails" description="Create plot grids for ROI file.">
+			<ITEM name="write-ctd-file-ext" value="" type="string" description="Override file extension for --write-ctd" required="false" advanced="true" />
+			<ITEM name="verbose" value="false" type="string" description="Verbose mode." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="vverbose" value="false" type="string" description="Very verbose mode." restrictions="true,false" required="false" advanced="false" />
+			<ITEM name="input-file" value="" type="input-file" description="ROI to plot." supported_formats="*.roi" required="true" advanced="false" />
+			<ITEM name="input-file-file-ext" value="" type="string" description="Override file extension for --input-file" restrictions="roi" required="false" advanced="true" />
+			<ITEM name="output-prefix" value="" type="output-file" description="Prefix of output file." required="true" advanced="false" />
+			<ITEM name="output-prefix-file-ext" value="" type="string" description="Override file extension for --output-prefix" required="false" advanced="true" />
+			<ITEM name="max-rois" value="20000" type="int" description="Maximal number of plots to create (0 for all)." restrictions="0:" required="false" advanced="false" />
+			<ITEM name="max-value" value="0" type="int" description="Fix maximal y value.  0 for no limit.." restrictions="0:" required="false" advanced="false" />
+			<ITEM name="num-cols" value="40" type="int" description="Number of plots in one row." restrictions="1:" required="false" advanced="false" />
+			<ITEM name="num-rows" value="50" type="int" description="Number of plots in one column." restrictions="1:" required="false" advanced="false" />
+			<ITEM name="plot-height" value="30" type="int" description="Height of one plot in px." restrictions="1:" required="false" advanced="false" />
+			<ITEM name="plot-width" value="30" type="int" description="Width of one plot in px." restrictions="1:" required="false" advanced="false" />
+			<ITEM name="border-width" value="0" type="int" description="Border width." restrictions="0:" required="false" advanced="false" />
+			<ITEM name="spacing" value="2" type="int" description="Space between plots." required="false" advanced="false" />
+		</NODE>
+	</PARAMETERS>
+</tool>
--- a/roi_plot_thumbnails.xml	Fri Jun 28 14:01:42 2013 -0400
+++ b/roi_plot_thumbnails.xml	Mon Aug 12 09:58:57 2013 -0400
@@ -17,24 +17,6 @@
     #if $ucsc_org    # --ucsc-org $ucsc_org #end if
     #if $ucsc_db     # --ucsc-db $ucsc_db #end if
     #if $ucsc_chr_prefix # --ucsc-chr-prefix "$ucsc_chr_prefix" #end if
-
-    &amp;&amp;
-
-    ln -s ${input} ${input}.${input.ext}
-
-    ;
-
-    roi_plot_thumbnails -if $input -o "${out_file.files_path}/thumbnail_"
-    #if $max_rois    # --max-rois $max_rois #end if
-    #if $num_rows    # --num-rows $num_rows #end if
-    #if $num_cols    # --num-cols $num_cols #end if
-    #if $plot_height # --plot-height $plot_height #end if
-    #if $plot_width  # --plot-width $plot_width #end if
-    #if $max_value   # --max-value $max_value #end if
-
-    ;
-
-    rm -f ${input}.${input.ext}
   </command>
   <inputs>
     <param name="input" format="roi" type="data" label="ROI file to generate statistics for."/>