Repository 'jbrowse'
hg clone https://toolshed.g2.bx.psu.edu/repos/iuc/jbrowse

Changeset 1:497c6bb3b717 (2015-06-18)
Previous changeset 0:2c9e5136b416 (2015-05-04) Next changeset 2:b6a0e126dbee (2015-06-23)
Commit message:
planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/jbrowse commit 0887009a23d176b21536c9fd8a18c4fecc417d4f
modified:
jbrowse.py
jbrowse.xml
macros.xml
readme.rst
test-data/interpro.gff
test-data/merlin.fa
test-data/merlin.gff
tool_dependencies.xml
added:
blastxml_to_gapped_gff3.py
gff3_rebase.py
test-data/154.bam
test-data/154.bam.bai
test-data/154.bw
test-data/blast.xml
test-data/test.vcf
test-data/xmfa.gff
test.yml
b
diff -r 2c9e5136b416 -r 497c6bb3b717 blastxml_to_gapped_gff3.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/blastxml_to_gapped_gff3.py Thu Jun 18 12:10:51 2015 -0400
[
b'@@ -0,0 +1,256 @@\n+#!/usr/bin/perl\n+import re\n+import sys\n+import copy\n+import argparse\n+from BCBio import GFF\n+import logging\n+logging.basicConfig(level=logging.INFO)\n+log = logging.getLogger(name=\'blastxml2gff3\')\n+\n+__author__ = "Eric Rasche"\n+__version__ = "0.4.0"\n+__maintainer__ = "Eric Rasche"\n+__email__ = "esr@tamu.edu"\n+\n+__doc__ = """\n+BlastXML files, when transformed to GFF3, do not normally show gaps in the\n+blast hits. This tool aims to fill that "gap".\n+"""\n+\n+\n+def blastxml2gff3(blastxml, min_gap=3, trim=False, trim_end=False):\n+    from Bio.Blast import NCBIXML\n+    from Bio.Seq import Seq\n+    from Bio.SeqRecord import SeqRecord\n+    from Bio.SeqFeature import SeqFeature, FeatureLocation\n+\n+    blast_records = NCBIXML.parse(blastxml)\n+    records = []\n+    for record in blast_records:\n+        rec = SeqRecord(Seq("ACTG"), id=record.query)\n+        for hit in record.alignments:\n+            for hsp in hit.hsps:\n+                qualifiers = {\n+                    "source": "blast",\n+                    "score": hsp.expect,\n+                    "accession": hit.accession,\n+                    "hit_id": hit.hit_id,\n+                    "length": hit.length,\n+                    "hit_titles": hit.title.split(\' >\')\n+                }\n+                desc = hit.title.split(\' >\')[0]\n+                qualifiers[\'description\'] = desc[desc.index(\' \'):]\n+\n+                # This required a fair bit of sketching out/match to figure out\n+                # the first time.\n+                #\n+                # the match_start location must account for queries and\n+                # subjecst that start at locations other than 1\n+                parent_match_start = hsp.query_start - hsp.sbjct_start\n+                # The end is the start + hit.length because the match itself\n+                # may be longer than the parent feature, so we use the supplied\n+                # subject/hit length to calculate the real ending of the target\n+                # protein.\n+                parent_match_end = hsp.query_start + hit.length + hsp.query.count(\'-\')\n+\n+                # However, if the user requests that we trim the feature, then\n+                # we need to cut the ``match`` start to 0 to match the parent feature.\n+                # We\'ll also need to cut the end to match the query\'s end. It (maybe)\n+                # should be the feature end? But we don\'t have access to that data, so\n+                # We settle for this.\n+                if trim:\n+                    if parent_match_start < 1:\n+                        parent_match_start = 0\n+\n+                if trim or trim_end:\n+                    if parent_match_end > hsp.query_end:\n+                        parent_match_end = hsp.query_end + 1\n+\n+                # The ``protein_match`` feature will hold one or more ``match_part``s\n+                top_feature = SeqFeature(\n+                    FeatureLocation(parent_match_start, parent_match_end),\n+                    type="protein_match", strand=0,\n+                    qualifiers=qualifiers\n+                )\n+\n+                # Unlike the parent feature, ``match_part``s have sources.\n+                part_qualifiers = {\n+                    "source": "blast",\n+                }\n+                top_feature.sub_features = []\n+                for start, end, cigar in generate_parts(hsp.query, hsp.match,\n+                                                        hsp.sbjct,\n+                                                        ignore_under=min_gap):\n+                    part_qualifiers[\'Gap\'] = cigar\n+                    part_qualifiers[\'ID\'] = hit.hit_id\n+\n+                    if trim:\n+                        # If trimming, then we start relative to the\n+                        # protein_match\'s start\n+                        match_part_start = parent_match_start + start\n+                    else:\n+                        # Otherwise, we have to account for the subject start\'s location\n+                        match_'..b':\n+\n+        Q:ACTGACTGACTG\n+        S:ACTGAC---CTG\n+\n+    which greatly simplifies the process of identifying the correct location\n+    for a match_part\n+    """\n+    prev = 0\n+    fq = \'\'\n+    fm = \'\'\n+    fs = \'\'\n+    for position in re.finditer(\'-\', query):\n+        fq += query[prev:position.start()]\n+        fm += match[prev:position.start()]\n+        fs += subject[prev:position.start()]\n+        prev = position.start() + 1\n+    fq += query[prev:]\n+    fm += match[prev:]\n+    fs += subject[prev:]\n+\n+    return (fq, fm, fs)\n+\n+\n+def generate_parts(query, match, subject, ignore_under=3):\n+    region_q = []\n+    region_m = []\n+    region_s = []\n+\n+    (query, match, subject) = __remove_query_gaps(query, match, subject)\n+\n+    region_start = -1\n+    region_end = -1\n+    mismatch_count = 0\n+    for i, (q, m, s) in enumerate(zip(query, match, subject)):\n+\n+        # If we have a match\n+        if m != \' \' or m == \'+\':\n+            if region_start == -1:\n+                region_start = i\n+                # It\'s a new region, we need to reset or it\'s pre-seeded with\n+                # spaces\n+                region_q = []\n+                region_m = []\n+                region_s = []\n+            region_end = i\n+            mismatch_count = 0\n+        else:\n+            mismatch_count += 1\n+\n+        region_q.append(q)\n+        region_m.append(m)\n+        region_s.append(s)\n+\n+        if mismatch_count >= ignore_under and region_start != -1 and region_end != -1:\n+            region_q = region_q[0:-ignore_under]\n+            region_m = region_m[0:-ignore_under]\n+            region_s = region_s[0:-ignore_under]\n+            yield region_start, region_end + 1, \\\n+                cigar_from_string(region_q, region_m, region_s, strict_m=True)\n+            region_q = []\n+            region_m = []\n+            region_s = []\n+\n+            region_start = -1\n+            region_end = -1\n+            mismatch_count = 0\n+\n+    yield region_start, region_end + 1, \\\n+        cigar_from_string(region_q, region_m, region_s, strict_m=True)\n+\n+\n+def _qms_to_matches(query, match, subject, strict_m=True):\n+    matchline = []\n+\n+    for (q, m, s) in zip(query, match, subject):\n+        ret = \'\'\n+\n+        if m != \' \' or m == \'+\':\n+            ret = \'=\'\n+        elif m == \' \':\n+            if q == \'-\':\n+                ret = \'D\'\n+            elif s == \'-\':\n+                ret = \'I\'\n+            else:\n+                ret = \'X\'\n+        else:\n+            log.warn("Bad data: \\n\\t%s\\n\\t%s\\n\\t%s\\n" % (query, match, subject))\n+\n+\n+        if strict_m:\n+            if ret == \'=\' or ret == \'X\':\n+                ret = \'M\'\n+\n+        matchline.append(ret)\n+    return matchline\n+\n+\n+def _matchline_to_cigar(matchline):\n+    cigar_line = []\n+    last_char = matchline[0]\n+    count = 0\n+    for char in matchline:\n+        if char == last_char:\n+            count += 1\n+        else:\n+            cigar_line.append("%s%s" % (last_char, count))\n+            count = 1\n+        last_char = char\n+    cigar_line.append("%s%s" % (last_char, count))\n+    return \' \'.join(cigar_line)\n+\n+\n+def cigar_from_string(query, match, subject, strict_m=True):\n+    matchline = _qms_to_matches(query, match, subject, strict_m=strict_m)\n+    if len(matchline) > 0:\n+        return _matchline_to_cigar(matchline)\n+    else:\n+        return ""\n+\n+\n+if __name__ == \'__main__\':\n+    parser = argparse.ArgumentParser(description=\'Convert Blast XML to gapped GFF3\', epilog=\'\')\n+    parser.add_argument(\'blastxml\', type=file, help=\'Blast XML Output\')\n+    parser.add_argument(\'--min_gap\', type=int, help=\'Maximum gap size before generating a new match_part\', default=3)\n+    parser.add_argument(\'--trim\', action=\'store_true\', help=\'Trim blast hits to be only as long as the parent feature\')\n+    parser.add_argument(\'--trim_end\', action=\'store_true\', help=\'Cut blast results off at end of gene\')\n+    args = parser.parse_args()\n+\n+    result = blastxml2gff3(**vars(args))\n+\n+    GFF.write(result, sys.stdout)\n'
b
diff -r 2c9e5136b416 -r 497c6bb3b717 gff3_rebase.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gff3_rebase.py Thu Jun 18 12:10:51 2015 -0400
[
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+import sys
+import logging
+logging.basicConfig(level=logging.INFO)
+import argparse
+from BCBio import GFF
+from Bio.SeqFeature import FeatureLocation
+log = logging.getLogger(__name__)
+
+__author__ = "Eric Rasche"
+__version__ = "0.4.0"
+__maintainer__ = "Eric Rasche"
+__email__ = "esr@tamu.edu"
+
+
+def __get_features(child, interpro=False):
+    child_features = {}
+    for rec in GFF.parse(child):
+        for feature in rec.features:
+            parent_feature_id = rec.id
+            if interpro:
+                if feature.type == 'polypeptide':
+                    continue
+                if '_' in parent_feature_id:
+                    parent_feature_id = parent_feature_id[parent_feature_id.index('_') + 1:]
+
+            try:
+                child_features[parent_feature_id].append(feature)
+            except KeyError:
+                child_features[parent_feature_id] = [feature]
+    return child_features
+
+
+def __update_feature_location(feature, parent, protein2dna):
+    start = feature.location.start
+    end = feature.location.end
+    if protein2dna:
+        start *= 3
+        end *= 3
+
+    if parent.location.strand >= 0:
+        ns = parent.location.start + start
+        ne = parent.location.start + end
+        st = +1
+    else:
+        ns = parent.location.end - end
+        ne = parent.location.end - start
+        st = -1
+
+    # Don't let start/stops be less than zero. It's technically valid for them
+    # to be (at least in the model I'm working with) but it causes numerous
+    # issues.
+    #
+    # Instead, we'll replace with %3 to try and keep it in the same reading
+    # frame that it should be in.
+    if ns < 0:
+        ns %= 3
+    if ne < 0:
+        ne %= 3
+
+    feature.location = FeatureLocation(ns, ne, strand=st)
+
+    if hasattr(feature, 'sub_features'):
+        for subfeature in feature.sub_features:
+            __update_feature_location(subfeature, parent, protein2dna)
+
+
+def rebase(parent, child, interpro=False, protein2dna=False):
+    child_features = __get_features(child, interpro=interpro)
+
+    for rec in GFF.parse(parent):
+        # TODO, replace with recursion in case it's matched against a
+        # non-parent feature. We're cheating a bit here right now...
+        replacement_features = []
+        for feature in rec.features:
+            if feature.id in child_features:
+                new_subfeatures = child_features[feature.id]
+                # TODO: update starts
+                fixed_subfeatures = []
+                for x in new_subfeatures:
+                    # Then update the location of the actual feature
+                    __update_feature_location(x, feature, protein2dna)
+
+                    if interpro:
+                        for y in ('status', 'Target'):
+                            try:
+                                del x.qualifiers[y]
+                            except:
+                                pass
+
+                    fixed_subfeatures.append(x)
+                replacement_features.extend(fixed_subfeatures)
+        # We do this so we don't include the original set of features that we
+        # were rebasing against in our result.
+        rec.features = replacement_features
+        GFF.write([rec], sys.stdout)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='rebase gff3 features against parent locations', epilog="")
+    parser.add_argument('parent', type=file, help='Parent GFF3 annotations')
+    parser.add_argument('child', help='Child GFF3 annotations to rebase against parent')
+    parser.add_argument('--interpro', action='store_true',
+                        help='Interpro specific modifications')
+    parser.add_argument('--protein2dna', action='store_true',
+                        help='Map protein translated results to original DNA data')
+    args = parser.parse_args()
+    rebase(**vars(args))
b
diff -r 2c9e5136b416 -r 497c6bb3b717 jbrowse.py
--- a/jbrowse.py Mon May 04 17:21:38 2015 -0400
+++ b/jbrowse.py Thu Jun 18 12:10:51 2015 -0400
[
b'@@ -1,9 +1,45 @@\n #!/usr/bin/env python\n+from string import Template\n import os\n-import shutil\n import argparse\n import subprocess\n import hashlib\n+import tempfile\n+import json\n+import yaml\n+import logging\n+logging.basicConfig()\n+log = logging.getLogger(__name__)\n+\n+COLOR_FUNCTION_TEMPLATE = Template("""\n+function(feature, variableName, glyphObject, track) {\n+    var score = ${score};\n+    ${opacity}\n+    return \'rgba(${red}, ${green}, ${blue}, \' + opacity + \')\';\n+}\n+""")\n+\n+BLAST_OPACITY_MATH = """\n+var opacity = 0;\n+if(score == 0.0) {\n+    opacity = 1;\n+} else{\n+    opacity = (20 - Math.log10(score)) / 180;\n+}\n+"""\n+\n+BREWER_COLOUR_IDX = 0\n+BREWER_COLOUR_SCHEMES = [\n+    (228, 26, 28),\n+    (55, 126, 184),\n+    (77, 175, 74),\n+    (152, 78, 163),\n+    (255, 127, 0),\n+]\n+\n+\n+# score comes from feature._parent.get(\'score\') or feature.get(\'score\')\n+# Opacity math\n \n TN_TABLE = {\n     \'gff3\': \'--gff\',\n@@ -12,40 +48,298 @@\n     # \'genbank\': \'--gbk\',\n }\n \n-\n-def process_genome(jbrowse_dir, genome):\n-    subprocess.check_output([\'perl\', \'bin/prepare-refseqs.pl\', \'--fasta\', genome], cwd=jbrowse_dir)\n+INSTALLED_TO = os.path.dirname(os.path.realpath(__file__))\n \n \n-def process_annotations(jbrowse_dir, annot_file, annot_label, annot_format,\n-                        **kwargs):\n-    key = hashlib.md5(annot_file).hexdigest()\n+class JbrowseConnector(object):\n+\n+    def __init__(self, jbrowse, jbrowse_dir, outdir, genome):\n+        self.jbrowse = jbrowse\n+        self.jbrowse_dir = jbrowse_dir\n+        self.outdir = outdir\n+        self.genome_path = genome\n+        self.brewer_colour_idx = 0\n+\n+        self.clone_jbrowse(self.jbrowse, self.outdir)\n+        self.process_genome()\n+\n+    def subprocess_check_call(self, command):\n+        log.debug(\'cd %s && %s\', self.jbrowse_dir, \' \'.join(command))\n+        subprocess.check_call(command, cwd=self.jbrowse_dir)\n+\n+    def _get_colours(self):\n+        r, g, b = BREWER_COLOUR_SCHEMES[self.brewer_colour_idx]\n+        self.brewer_colour_idx += 1\n+        return r, g, b\n+\n+    def process_genome(self):\n+        self.subprocess_check_call([\'perl\', \'bin/prepare-refseqs.pl\',\n+                                    \'--fasta\', self.genome_path])\n+\n+    def _add_json(self, json_data):\n+        if len(json_data.keys()) == 0:\n+            return\n+\n+        tmp = tempfile.NamedTemporaryFile(delete=False)\n+        tmp.write(json.dumps(json_data))\n+        tmp.close()\n+        cmd = [\'perl\', \'bin/add-track-json.pl\', tmp.name,\n+               os.path.join(\'data\', \'trackList.json\')]\n+        self.subprocess_check_call(cmd)\n+        os.unlink(tmp.name)\n+\n+    def add_blastxml(self, data, key, **kwargs):\n+        gff3_unrebased = tempfile.NamedTemporaryFile(delete=False)\n+        cmd = [\'python\', os.path.join(INSTALLED_TO, \'blastxml_to_gapped_gff3.py\'),\n+               \'--trim_end\', \'--min_gap\', str(kwargs[\'min_gap\']), data]\n+        subprocess.check_call(cmd, cwd=self.jbrowse_dir, stdout=gff3_unrebased)\n+        gff3_unrebased.close()\n+\n+        gff3_rebased = tempfile.NamedTemporaryFile(delete=False)\n+        cmd = [\'python\', os.path.join(INSTALLED_TO, \'gff3_rebase.py\')]\n+        if kwargs[\'protein\']:\n+            cmd.append(\'--protein2dna\')\n+        cmd.extend([kwargs[\'parent\'], gff3_unrebased.name])\n+        subprocess.check_call(cmd, cwd=self.jbrowse_dir, stdout=gff3_rebased)\n+        gff3_rebased.close()\n+\n+        label = hashlib.md5(data).hexdigest()\n+\n+        red, green, blue = self._get_colours()\n+        color_function = COLOR_FUNCTION_TEMPLATE.substitute({\n+            \'score\': "feature._parent.get(\'score\')",\n+            \'opacity\': BLAST_OPACITY_MATH,\n+            \'red\': red,\n+            \'green\': green,\n+            \'blue\': blue,\n+        })\n+\n+        clientConfig = {\n+            \'label\': \'description\',\n+            \'color\': color_function.replace(\'\\n\', \'\'),\n+            \'description\': \'Hit_titles\',\n+        }\n+        config = {\'glyph\': \'JBrowse/View/FeatureGlyph/Segments\'}\n+        if \'category\' i'..b'eplace(\'\\n\', \'\')\n+\n+            config[\'glyph\'] = \'JBrowse/View/FeatureGlyph/Segments\'\n+\n+            cmd += [\'--clientConfig\', json.dumps(clientConfig),\n+                    \'--trackType\', \'JBrowse/View/Track/CanvasFeatures\'\n+                    ]\n+\n+        cmd.extend([\'--config\', json.dumps(config)])\n+\n+        self.subprocess_check_call(cmd)\n+\n+    def process_annotations(self, data, key, format, **kwargs):\n+        if format in (\'gff\', \'gff3\', \'bed\'):\n+            self.add_features(data, key, format, **kwargs)\n+        elif format == \'bigwig\':\n+            self.add_bigwig(data, key, **kwargs)\n+        elif format == \'bam\':\n+            self.add_bam(data, key, **kwargs)\n+        elif format == \'blastxml\':\n+            self.add_blastxml(data, key, **kwargs)\n+        elif format == \'vcf\':\n+            self.add_vcf(data, key, **kwargs)\n+\n+    def clone_jbrowse(self, jbrowse_dir, destination):\n+        # JBrowse seems to have included some bad symlinks, cp ignores bad symlinks\n+        # unlike copytree\n+        cmd = [\'mkdir\', \'-p\', destination]\n+        subprocess.check_call(cmd)\n+        cmd = [\'cp\', \'-r\', jbrowse_dir, destination]\n+        subprocess.check_call(cmd)\n+        cmd = [\'mkdir\', \'-p\', os.path.join(destination, \'JBrowse-1.11.6\',\n+                                           \'data\', \'raw\')]\n+        subprocess.check_call(cmd)\n+\n+        # http://unix.stackexchange.com/a/38691/22785\n+        # JBrowse releases come with some broken symlinks\n+        cmd = [\'find\', destination, \'-type\', \'l\', \'-xtype\', \'l\', \'-exec\', \'rm\', "\'{}\'", \'+\']\n+        subprocess.check_call(cmd)\n \n \n if __name__ == \'__main__\':\n     parser = argparse.ArgumentParser(description="", epilog="")\n     parser.add_argument(\'genome\', type=file, help=\'Input genome file\')\n-\n-    parser.add_argument(\'--gff3\', type=file, nargs=\'*\', help=\'GFF3/BED/GBK File\')\n-    parser.add_argument(\'--gff3_format\', choices=[\'gff3\', \'gff\', \'bed\', \'gbk\'], nargs=\'*\', help=\'GFF3/BED/GBK Format\')\n-    parser.add_argument(\'--gff3_label\', type=str, nargs=\'*\', help=\'GFF3/BED/GBK Label\')\n+    parser.add_argument(\'yaml\', type=file, help=\'Track Configuration\')\n \n     parser.add_argument(\'--jbrowse\', help=\'Folder containing a jbrowse release\')\n     parser.add_argument(\'--outdir\', help=\'Output directory\', default=\'out\')\n     args = parser.parse_args()\n \n-    jbrowse_dir = os.path.join(args.outdir, \'JBrowse-1.11.6\')\n-    shutil.copytree(args.jbrowse, jbrowse_dir)\n+    jc = JbrowseConnector(\n+        jbrowse=args.jbrowse,\n+        jbrowse_dir=os.path.join(args.outdir, \'JBrowse-1.11.6\'),\n+        outdir=args.outdir,\n+        genome=os.path.realpath(args.genome.name),\n+    )\n \n-    process_genome(jbrowse_dir, os.path.realpath(args.genome.name))\n+    track_data = yaml.load(args.yaml)\n+    for track in track_data:\n+        path = os.path.realpath(track[\'file\'])\n+        extra = track.get(\'options\', {})\n+        if \'__unused__\' in extra:\n+            del extra[\'__unused__\']\n \n-    for gff3, gff3_format, gff3_label in zip(args.gff3, args.gff3_format, args.gff3_label):\n-        gff3_path = os.path.realpath(gff3.name)\n-        process_annotations(jbrowse_dir, gff3_path, gff3_label, gff3_format)\n+        for possible_partial_path in (\'bam_index\', \'parent\'):\n+            if possible_partial_path in extra:\n+                extra[possible_partial_path] = os.path.realpath(\n+                    extra[possible_partial_path])\n+        extra[\'category\'] = track.get(\'category\', \'Default\')\n+\n+        jc.process_annotations(path, track[\'label\'], track[\'ext\'], **extra)\n \n     print """\n     <html>\n@@ -54,6 +348,9 @@\n             window.location=JBrowse-1.11.6/index.html\n         </script>\n         <a href="JBrowse-1.11.6/index.html">Go to JBrowse</a>\n+        <p>Please note that JBrowse functions best on production Galaxy\n+        instances. The paste server used in development instances has issues\n+        serving the volumes of data regularly involved in JBrowse</p>\n         </body>\n     </html>\n     """\n'
b
diff -r 2c9e5136b416 -r 497c6bb3b717 jbrowse.xml
--- a/jbrowse.xml Mon May 04 17:21:38 2015 -0400
+++ b/jbrowse.xml Thu Jun 18 12:10:51 2015 -0400
[
@@ -1,4 +1,4 @@
-<tool id="jbrowse" name="JBrowse" version="0.1">
+<tool id="jbrowse" name="JBrowse" version="0.3">
   <description>genome browser</description>
   <macros>
     <import>macros.xml</import>
@@ -8,25 +8,116 @@
   <version_command>python jbrowse.py --version</version_command>
   <command interpreter="python"><![CDATA[jbrowse.py
 $positional_1
-
-#set data_files = '" "'.join([ str($var.gff3) for $var in $data_tracks ])
-#set data_formats  = '" "'.join([ str($var.gff3.ext) for $var in $data_tracks ])
-#set data_labels = '" "'.join([ str($var.gff3_label) for $var in $data_tracks ])
-
---gff3 "$data_files"
---gff3_format "$data_formats"
---gff3_label "$data_labels"
-
+$trackYaml
 
 --jbrowse \${JBROWSE_SOURCE_DIR}
 --outdir $default.files_path
 > $default]]></command>
+  <configfiles>
+      <configfile name="trackYaml">
+---
+#for $track in $data_tracks:
+  -
+    file: ${track.data_format.annotation}
+    ext: ${track.data_format.annotation.ext}
+    label: "${track.annotation_label}"
+    category: "${track.category}"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+    #if str($track.data_format.data_format_select) == "wiggle":
+        type: ${track.data_format.xyplot}
+        variance_band: ${track.data_format.var_band}
+      #if str($track.data_format.scaling.scale_select) == "auto_local":
+        autoscale: local
+      #else if str($track.data_format.scaling.scale_select) == "auto_global":
+        autoscale: global
+      #else:
+        min: ${track.data_format.scaling.minimum}
+        max: ${track.data_format.scaling.maximum}
+      #end if
+    #else if str($track.data_format.data_format_select) == "pileup":
+        auto_snp: ${track.data_format.auto_snp}
+        bam_index: ${track.data_format.annotation.metadata.bam_index}
+    #else if str($track.data_format.data_format_select) == "blast":
+        parent: ${track.data_format.blast_parent}
+        protein: ${track.data_format.is_protein}
+        min_gap: ${track.data_format.min_gap}
+        match: true
+    #else if str($track.data_format.data_format_select) == "gene_calls":
+        match: ${track.data_format.match_part}
+    #end if
+#end for
+      </configfile>
+  </configfiles>
   <inputs>
     <param label="Genome" name="positional_1" type="data" format="fasta"/>
     <repeat name="data_tracks" title="Annotation Track">
-        <param label="Annotation Data" help="in GFF, GFF3, or BED formats"
-            format="gff,gff3,bed" name="gff3" type="data"/>
-      <param label="Dataset Label" name="gff3_label" type="text"/>
+        <param label="Track Label" name="annotation_label" type="text"/>
+        <param label="Track Category" name="category" type="text" value="Default"
+            help="Organise your tracks into Categories for a nicer end-user experience"/>
+        <conditional name="data_format" label="Track Options">
+            <param type="select" label="Track Type" name="data_format_select">
+                <option value="gene_calls">GFF/GFF3/BED Featuers</option>
+                <option value="pileup">BAM Pileups</option>
+                <option value="blast">Blast XML</option>
+                <option value="wiggle">BigWig XY</option>
+                <option value="vcf">VCF SNPs</option>
+            </param>
+            <when value="blast">
+                <param label="BlastXML Track Data" format="blastxml" name="annotation" type="data"/>
+
+                <param label="Features used in Blast Search" help="in GFF3. This is required so we know where to map features. E.g. where results of which CDS Protein32 match up to. The query IDs in your blast results should MATCH some feature IDs in your GFF3 file."
+                    format="gff3" name="blast_parent" type="data"/>
+
+                <param label="Minimum Gap Size" help="before a new match_part feature is created" name="min_gap"
+                    type="integer" value="10" min="2" />
+                <param label="Is this a protein blast search?"
+                    type="boolean" name="is_protein" truevalue="true" falsevalue="false" />
+            </when>
+            <when value="vcf">
+                <param label="SNPs" help="in VCF"
+                    format="vcf" name="annotation" type="data"/>
+            </when>
+            <when value="gene_calls">
+                <param label="Track Data" help="in GFF, GFF3, BED"
+                    format="gff,gff3,bed" name="annotation" type="data"/>
+
+                <param label="This is match/match_part data"
+                    type="boolean" name="match_part" truevalue="true" falsevalue="false" />
+            </when>
+            <when value="pileup">
+                <param label="Track Data" help="in BAM"
+                    format="bam" name="annotation" type="data"/>
+                <param label="Autogenerate SNP Track" help="Not recommended for deep coverage BAM files"
+                    type="boolean" name="auto_snp" truevalue="true" falsevalue="false" />
+            </when>
+            <when value="wiggle">
+                <param label="Track Data" help="in BigWig"
+                    format="bigwig" name="annotation" type="data"/>
+                <param label="Use XYPlot" help="instead of continuous coloured band"
+                    type="boolean" name="xyplot" truevalue="JBrowse/View/Track/Wiggle/XYPlot"
+                    falsevalue="JBrowse/View/Track/Wiggle/Density" />
+                <param label="Show variance band" help="Only for XYPlots"
+                    type="boolean" name="var_band" truevalue="true"
+                    falsevalue="false" />
+
+                <conditional name="scaling" label="Scaling">
+                    <param type="select" label="Track Scaling" name="scale_select">
+                        <option value="auto_local">Autoscale (local)</option>
+                        <option value="auto_global">Autoscale (global)</option>
+                        <option vlue="fixed">Specify Min/Max</option>
+                    </param>
+                    <when value="auto_local"></when>
+                    <when value="auto_global"></when>
+                    <when value="fixed">
+                        <param label="Track minimum" name="minimum"
+                            type="integer" value="0" />
+                        <param label="Track maximum" name="maximum"
+                            type="integer" value="100" />
+                    </when>
+                </conditional>
+            </when>
+        </conditional>
     </repeat>
   </inputs>
   <outputs>
b
diff -r 2c9e5136b416 -r 497c6bb3b717 macros.xml
--- a/macros.xml Mon May 04 17:21:38 2015 -0400
+++ b/macros.xml Thu Jun 18 12:10:51 2015 -0400
b
@@ -3,6 +3,10 @@
   <xml name="requirements">
     <requirements>
       <requirement type="package" version="1.11.6">jbrowse</requirement>
+      <requirement type="package" version="2.7">python</requirement>
+      <requirement type="package" version="5.18">perl</requirement>
+      <requirement type="package" version="1.2">samtools</requirement>
+      <requirement type="package" version="1.0">bundle_jbrowse</requirement>
       <yield/>
     </requirements>
   </xml>
b
diff -r 2c9e5136b416 -r 497c6bb3b717 readme.rst
--- a/readme.rst Mon May 04 17:21:38 2015 -0400
+++ b/readme.rst Thu Jun 18 12:10:51 2015 -0400
b
@@ -13,10 +13,19 @@
 
 It is recommended to install this wrapper via the Galaxy Tool Shed
 
+Running Locally
+===============
+
+The Galaxy tool interface writes out a yaml file which is then used to generate
+the visualizations. An example used during development/testing can be seen in
+`test.yml`. The format is in no way rigorously defined and is likely to change
+at any time.
+
 History
 =======
 
 -  0.1 Initial public release
+-  0.2 Added support for BAM, Blast, VCF
 
 Wrapper License (MIT/BSD Style)
 ===============================
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/154.bam
b
Binary file test-data/154.bam has changed
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/154.bam.bai
b
Binary file test-data/154.bam.bai has changed
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/154.bw
b
Binary file test-data/154.bw has changed
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/blast.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/blast.xml Thu Jun 18 12:10:51 2015 -0400
[
b'@@ -0,0 +1,4514 @@\n+<?xml version="1.0"?>\n+<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">\n+<BlastOutput>\n+  <BlastOutput_program>blastp</BlastOutput_program>\n+  <BlastOutput_version>BLASTP 2.2.28+</BlastOutput_version>\n+  <BlastOutput_reference>Stephen F. Altschul, Thomas L. Madden, Alejandro A. Sch&amp;auml;ffer, Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), &quot;Gapped BLAST and PSI-BLAST: a new generation of protein database search programs&quot;, Nucleic Acids Res. 25:3389-3402.</BlastOutput_reference>\n+  <BlastOutput_db>/usr/local/syncdb/community/nr/nr</BlastOutput_db>\n+  <BlastOutput_query-ID>Query_1</BlastOutput_query-ID>\n+  <BlastOutput_query-def>Merlin_1</BlastOutput_query-def>\n+  <BlastOutput_query-len>229</BlastOutput_query-len>\n+  <BlastOutput_param>\n+    <Parameters>\n+      <Parameters_matrix>BLOSUM62</Parameters_matrix>\n+      <Parameters_expect>0.001</Parameters_expect>\n+      <Parameters_gap-open>11</Parameters_gap-open>\n+      <Parameters_gap-extend>1</Parameters_gap-extend>\n+      <Parameters_filter>F</Parameters_filter>\n+    </Parameters>\n+  </BlastOutput_param>\n+<BlastOutput_iterations>\n+<Iteration>\n+  <Iteration_iter-num>1</Iteration_iter-num>\n+  <Iteration_query-ID>Query_1</Iteration_query-ID>\n+  <Iteration_query-def>Merlin_1</Iteration_query-def>\n+  <Iteration_query-len>229</Iteration_query-len>\n+<Iteration_hits>\n+<Hit>\n+  <Hit_num>1</Hit_num>\n+  <Hit_id>gi|422934611|ref|YP_007004572.1|</Hit_id>\n+  <Hit_def>hypothetical protein [Enterobacteria phage ime09] &gt;gi|339791394|gb|AEK12451.1| hypothetical protein [Enterobacteria phage ime09]</Hit_def>\n+  <Hit_accession>YP_007004572</Hit_accession>\n+  <Hit_len>685</Hit_len>\n+  <Hit_hsps>\n+    <Hsp>\n+      <Hsp_num>1</Hsp_num>\n+      <Hsp_bit-score>197.593</Hsp_bit-score>\n+      <Hsp_score>501</Hsp_score>\n+      <Hsp_evalue>3.74548e-55</Hsp_evalue>\n+      <Hsp_query-from>2</Hsp_query-from>\n+      <Hsp_query-to>229</Hsp_query-to>\n+      <Hsp_hit-from>474</Hsp_hit-from>\n+      <Hsp_hit-to>684</Hsp_hit-to>\n+      <Hsp_query-frame>0</Hsp_query-frame>\n+      <Hsp_hit-frame>0</Hsp_hit-frame>\n+      <Hsp_identity>106</Hsp_identity>\n+      <Hsp_positive>154</Hsp_positive>\n+      <Hsp_gaps>21</Hsp_gaps>\n+      <Hsp_align-len>230</Hsp_align-len>\n+      <Hsp_qseq>LDKGTLLYRGQKLDLPTFEHNAENKLFYFRNYVSTSLKPLIFGEFGRMFMALDDDTTIYTAETPDDYNRFANPEDIIDIGATQKDSFDDNNNDGTSINIGKQVNLGFVISGAENVRVIVPGSLTEYPEEAEVILPRGTLLKINKITTQVDKRS--NKFMVEGSIVPPSEQIDESVEIYDGDLFMETGEVVKLSGFMQFVNESAYDEEQNQMAAEILSGFLDIDDMPRKFR</Hsp_qseq>\n+      <Hsp_hseq>LPPGTTLYRGQEVTFKTLRHNIENKMFYFKNFVSTSLKPNIFGEHGKNYMALDDSGAVFSGEGEGS----VDAEDLMHMGSHSAYANED-----------AETSVGMVIKGAERIKVIVPGHLSGFPSEAEVILPRGILLKINKVSTYMMKETAYNKYLIEGTIVPPSEQLEESV--YDGDHLMETGEVRPMAGFNQFLVEES--KEEENEVSQILASLVNINGMSKKFK</Hsp_hseq>\n+      <Hsp_midline>L  GT LYRGQ++   T  HN ENK+FYF+N+VSTSLKP IFGE G+ +MALDD   +++ E         + ED++ +G+    + +D            + ++G VI GAE ++VIVPG L+ +P EAEVILPRG LLKINK++T + K +  NK+++EG+IVPPSEQ++ESV  YDGD  METGEV  ++GF QF+ E +  +E+    ++IL+  ++I+ M +KF+</Hsp_midline>\n+    </Hsp>\n+  </Hit_hsps>\n+</Hit>\n+<Hit>\n+  <Hit_num>2</Hit_num>\n+  <Hit_id>gi|330858714|ref|YP_004415089.1|</Hit_id>\n+  <Hit_def>hypothetical protein Shfl2p198 [Shigella phage Shfl2] &gt;gi|327397648|gb|AEA73150.1| hypothetical protein Shfl2p198 [Shigella phage Shfl2]</Hit_def>\n+  <Hit_accession>YP_004415089</Hit_accession>\n+  <Hit_len>685</Hit_len>\n+  <Hit_hsps>\n+    <Hsp>\n+      <Hsp_num>1</Hsp_num>\n+      <Hsp_bit-score>197.593</Hsp_bit-score>\n+      <Hsp_score>501</Hsp_score>\n+      <Hsp_evalue>4.31042e-55</Hsp_evalue>\n+      <Hsp_query-from>2</Hsp_query-from>\n+      <Hsp_query-to>229</Hsp_query-to>\n+      <Hsp_hit-from>474</Hsp_hit-from>\n+      <Hsp_hit-to>684</Hsp_hit-to>\n+      <Hsp_query-frame>0</Hsp_query-frame>\n+      <Hsp_hit-frame>0</Hsp_hit-frame>\n+      <Hsp_identity>106</Hsp_identity>\n+      <Hsp_positive>154</Hsp_positive>\n+      <Hsp_gaps>21</Hsp_gap'..b'e>0</Hsp_hit-frame>\n+      <Hsp_identity>150</Hsp_identity>\n+      <Hsp_positive>268</Hsp_positive>\n+      <Hsp_gaps>53</Hsp_gaps>\n+      <Hsp_align-len>553</Hsp_align-len>\n+      <Hsp_qseq>DVQSANELVAEVIEEKGNNL------IDSVDNVAEGTELAAEASERTTESIKTLTGVASTISDKLSKLASMLESKVQA--VEQKVQESGASASTGLSVIEDKLPDPDEPESPGLPERILPPLDDNNNLPDEDFFPPVPQEPENNKKDQKKDDKKPTDMLGD-LLKTTKGGFKATISITDKISSMLFKYTVTALAEAAKMAAMLFALVLGIDLLRIHFKYWTDKFMSNFDEFSAEAGEWGGLLQSIFGMLGDIKKFWEAGDWSGLAVAIVKGLADVIYNLSEIMSLGISKISASILDALGFENAATTIRGSALEGFQERTGNSLSEDDQKALAKYQSKRIEEGPGIIDKAGEFKTRAFDWVLGRENKIDSTQASDRDQETQNLKAMAPEKR---EETLIKQNEARAAVQRLEKYIGDVDPENPTNMQSLEKAYNSAKKSISDSAISDQPA---------TKKELDKRFQRVESKYQKLKEDNTPKPAA---PATSEDNQRVQNIQKAENAKE--QSKKSTGDMNVANTQVNNV-NNSKTIHQVQTVTATPAPGV</Hsp_qseq>\n+      <Hsp_hseq>DSLAAQELIAETVEQGNNELRQIKANTASLHDTAAATELGAESTEMSNTILREISETGKQTFSKLSEFAERLKGSFSADDVEQTPIRAASSSDQAIQIINEENPEPENPLVG-----YLRTISEDIKFLRENKNEPSDPKDPDVVPDDKDDLKTMIDRIGDQIVKSVDSGFKRTVNIADSISSTLFKYTITAALNFAKMAALVLSLIIAFDVLSRHFSHWTQMFQEQYAEFKETLGSFGTPFENLTGIVTDLVNYFKSDEYLKMFVRLAEGAADQMIYIVNMMMVGLAKLGAAILRALGADDKADTLEASAISVATKTVGYTPSEEEEATIGRVRKRQAQE---------EAEQSEASWWEKKKREWDG-----KPIETDEEKAVRERKKSIAENTTAEQFGKHDALSQKIQHVGVTAEKNETSNELLGKHRELLEKRASDVEQAKQSGEITTESYKQLKVEIEKQREFLDAHEQKL-----LKPKASIKPAPEPEIGVVGSIAKEEKRVEASQTAKQEAASNY-NTNANIVKNNNQTLVQAPR-TSSPGPGI</Hsp_hseq>\n+      <Hsp_midline>D  +A EL+AE +E+  N L        S+ + A  TEL AE++E +   ++ ++        KLS+ A  L+    A  VEQ    + +S+   + +I ++ P+P+ P         L  + ++     E+   P   +  +   D K D K   D +GD ++K+   GFK T++I D ISS LFKYT+TA    AKMAA++ +L++  D+L  HF +WT  F   + EF    G +G   +++ G++ D+  ++++ ++  + V + +G AD +  +  +M +G++K+ A+IL ALG ++ A T+  SA+    +  G + SE+++  + + + ++ +E         E +     W   ++ + D      +  ET   KA+   K+   E T  +Q     A+ +  +++G    +N T+ + L K     +K  SD   + Q            K E++K+ + +++  QKL      KP A   PA   +   V +I K E   E  Q+ K     N  NT  N V NN++T+ Q    T++P PG+</Hsp_midline>\n+    </Hsp>\n+  </Hit_hsps>\n+</Hit>\n+<Hit>\n+  <Hit_num>43</Hit_num>\n+  <Hit_id>gi|398313739|emb|CCI89086.1|</Hit_id>\n+  <Hit_def>phage baseplate hub [Yersinia phage phiD1]</Hit_def>\n+  <Hit_accession>CCI89086</Hit_accession>\n+  <Hit_len>191</Hit_len>\n+  <Hit_hsps>\n+    <Hsp>\n+      <Hsp_num>1</Hsp_num>\n+      <Hsp_bit-score>79.7221</Hsp_bit-score>\n+      <Hsp_score>195</Hsp_score>\n+      <Hsp_evalue>1.49556e-13</Hsp_evalue>\n+      <Hsp_query-from>2</Hsp_query-from>\n+      <Hsp_query-to>189</Hsp_query-to>\n+      <Hsp_hit-from>3</Hsp_hit-from>\n+      <Hsp_hit-to>187</Hsp_hit-to>\n+      <Hsp_query-frame>0</Hsp_query-frame>\n+      <Hsp_hit-frame>0</Hsp_hit-frame>\n+      <Hsp_identity>69</Hsp_identity>\n+      <Hsp_positive>102</Hsp_positive>\n+      <Hsp_gaps>17</Hsp_gaps>\n+      <Hsp_align-len>195</Hsp_align-len>\n+      <Hsp_qseq>KSENMSTMRRRKVIADSKGERDAASTASDQVDSLELIGLKLDDVQSANELVAEVIEEKGNNLIDSVDNV-------AEGTELAAEASERTTESIKTLTGVASTISDKLSKLASMLESKVQAVEQKVQESGASASTGLSVIEDKLPDPDEPESPGLPERILPPLDDNNNLPDEDFFPPVPQEPENNKKDQKKDDKK</Hsp_qseq>\n+      <Hsp_hseq>KPQEMQTMRR-KVISDNKPTQEAAKSASNTLSGLNDISTKLDDTQAASELIAQTVEEKSNEIVGAIGNVESAVSDTTAGSELIAETVEIGNNINKE---IGESLGSKLDKLTSLLEQKIQTA--GIQQTGTXLATVESAIPVKVVEDDTDRXXVLXYRXLKQLIMILTLI---FSLPLSQLSQ-SKNHQKKNRKK</Hsp_hseq>\n+      <Hsp_midline>K + M TMRR KVI+D+K  ++AA +AS+ +  L  I  KLDD Q+A+EL+A+ +EEK N ++ ++ NV         G+EL AE  E      K    +  ++  KL KL S+LE K+Q     +Q++G   +T  S I  K+ + D      L  R L  L     L    F  P+ Q  + +K  QKK+ KK</Hsp_midline>\n+    </Hsp>\n+  </Hit_hsps>\n+</Hit>\n+</Iteration_hits>\n+  <Iteration_stat>\n+    <Statistics>\n+      <Statistics_db-num>48094830</Statistics_db-num>\n+      <Statistics_db-len>17186091396</Statistics_db-len>\n+      <Statistics_hsp-len>153</Statistics_hsp-len>\n+      <Statistics_eff-space>4157067357738</Statistics_eff-space>\n+      <Statistics_kappa>0.041</Statistics_kappa>\n+      <Statistics_lambda>0.267</Statistics_lambda>\n+      <Statistics_entropy>0.14</Statistics_entropy>\n+    </Statistics>\n+  </Iteration_stat>\n+</Iteration>\n+</BlastOutput_iterations>\n+</BlastOutput>\n+\n'
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/test.vcf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/test.vcf Thu Jun 18 12:10:51 2015 -0400
b
@@ -0,0 +1,23 @@
+##fileformat=VCFv4.0
+##fileDate=20090805
+##source=myImputationProgramV3.1
+##reference=1000GenomesPilot-NCBI36
+##phasing=partial
+##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of Samples With Data">
+##INFO=<ID=DP,Number=1,Type=Integer,Description="Total Depth">
+##INFO=<ID=AF,Number=.,Type=Float,Description="Allele Frequency">
+##INFO=<ID=AA,Number=1,Type=String,Description="Ancestral Allele">
+##INFO=<ID=DB,Number=0,Type=Flag,Description="dbSNP membership, build 129">
+##INFO=<ID=H2,Number=0,Type=Flag,Description="HapMap2 membership">
+##FILTER=<ID=q10,Description="Quality below 10">
+##FILTER=<ID=s50,Description="Less than 50% of samples have data">
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+##FORMAT=<ID=GQ,Number=1,Type=Integer,Description="Genotype Quality">
+##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read Depth">
+##FORMAT=<ID=HQ,Number=2,Type=Integer,Description="Haplotype Quality">
+#CHROM POS     ID        REF ALT    QUAL FILTER INFO                              FORMAT      NA00001        NA00002        NA00003
+Merlin 14370 rs6054257 G A 29 PASS NS=3;DP=14;AF=0.5;DB;H2 GT:GQ:DP:HQ 0|0:48:1:51,51 1|0:48:8:51,51 1/1:43:5:.,.
+Merlin 17330 . T A 3 q10 NS=3;DP=11;AF=0.017 GT:GQ:DP:HQ 0|0:49:3:58,50 0|1:3:5:65,3 0/0:41:3
+Merlin 1110696 rs6040355 A G,T 67 PASS NS=2;DP=10;AF=0.333,0.667;AA=T;DB GT:GQ:DP:HQ 1|2:21:6:23,27 2|1:2:0:18,2 2/2:35:4
+Merlin 1230237 . T . 47 PASS NS=3;DP=13;AA=T GT:GQ:DP:HQ 0|0:54:7:56,60 0|0:48:4:51,51 0/0:61:2
+Merlin 1234567 microsat1 GTCT G,GTACT 50 PASS NS=3;DP=9;AA=G GT:GQ:DP 0/1:35:4 0/2:17:2 1/1:40:3
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test-data/xmfa.gff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/xmfa.gff Thu Jun 18 12:10:51 2015 -0400
b
b'@@ -0,0 +1,5918 @@\n+##gff-version 3\n+##sequence-region Merlin 1 172788\n+Merlin\tprogressiveMauve\tmatch\t123963\t171642\t.\t-\t.\tID=HM137666;Target=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t123963\t123982\t80\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t123983\t124032\t62\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124033\t124082\t86\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124083\t124132\t72\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124133\t124182\t78\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124183\t124232\t70\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124233\t124282\t48\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124283\t124329\t42.5531914894\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124469\t124494\t73.0769230769\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124495\t124544\t56\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124601\t124650\t56\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124651\t124700\t54\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124701\t124750\t56\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124751\t124796\t56.5217391304\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124797\t124846\t14\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124847\t124868\t27.2727272727\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124869\t124918\t68\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124919\t124964\t45.652173913\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t124965\t125009\t55.5555555556\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125010\t125059\t58\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125060\t125077\t33.3333333333\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125078\t125127\t64\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125128\t125177\t26\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125744\t125793\t66\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125794\t125843\t70\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125844\t125893\t64\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125894\t125943\t50\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125944\t125993\t54\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t125994\t126043\t52\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126044\t126093\t74\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126094\t126143\t48\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126144\t126193\t56\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126194\t126240\t57.4468085106\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126241\t126290\t64\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126291\t126333\t58.1395348837\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126334\t126378\t71.1111111111\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126379\t126425\t63.829787234\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126426\t126468\t67.4418604651\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126469\t126515\t74.4680851064\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126516\t126565\t60\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126566\t126603\t60.5263157895\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126604\t126653\t50\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126654\t126703\t66\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126704\t126753\t74\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126754\t126803\t70\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126804\t126853\t78\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126854\t126903\t78\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126904\t126953\t66\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t126954\t127003\t78\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t127004\t127053\t72\t+\t.\tParent=HM137666\n+Merlin\tprogressiveMauve\tmatch_part\t127054\t1271'..b'ogressiveMauve\tmatch_part\t168325\t168374\t84\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168375\t168424\t84\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168425\t168474\t78\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168475\t168524\t82\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168525\t168574\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168575\t168624\t70\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168625\t168674\t66\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t168675\t168724\t40\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169065\t169092\t60.7142857143\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169093\t169142\t74\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169143\t169192\t58\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169193\t169242\t60\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169243\t169292\t62\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169293\t169342\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169343\t169374\t59.375\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169375\t169423\t63.2653061224\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169424\t169473\t70\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169474\t169523\t70\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169524\t169573\t54\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169574\t169623\t54\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t169624\t169673\t40\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170000\t170040\t68.2926829268\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170041\t170082\t76.1904761905\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170083\t170132\t70\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170133\t170182\t56\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170183\t170232\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170233\t170282\t72\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170283\t170332\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170333\t170382\t72\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170383\t170431\t61.2244897959\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170432\t170473\t52.380952381\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170474\t170523\t58\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170524\t170573\t64\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170574\t170623\t42\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170824\t170849\t38.4615384615\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170850\t170898\t63.2653061224\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170899\t170948\t56\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170949\t170991\t67.4418604651\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t170992\t171040\t46.9387755102\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171041\t171090\t52\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171091\t171123\t69.696969697\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171124\t171167\t79.5454545455\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171168\t171217\t78\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171218\t171264\t57.4468085106\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171265\t171314\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171315\t171364\t68\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171365\t171414\t64\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171415\t171464\t76\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171465\t171514\t76\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171515\t171564\t80\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171565\t171614\t66\t+\t.\tParent=NC_000866\n+Merlin\tprogressiveMauve\tmatch_part\t171615\t171642\t53.5714285714\t+\t.\tParent=NC_000866\n+###\n'
b
diff -r 2c9e5136b416 -r 497c6bb3b717 test.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test.yml Thu Jun 18 12:10:51 2015 -0400
b
@@ -0,0 +1,54 @@
+---
+  -
+    file: test-data/154.bam
+    ext: bam
+    label: Sequencing Data
+    category: "Sequencing Data"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+        auto_snp: true
+        bam_index: test-data/154.bam.bai
+  -
+    file: test-data/merlin.gff
+    ext: gff3
+    label: "Gene Calls"
+    category: "Default"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+        match: false
+  -
+    file: test-data/154.bw
+    ext: bigwig
+    label: "Bigwig Test"
+    category: "Sequencing Data"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+        type: JBrowse/View/Track/Wiggle/XYPlot
+        variance_band: true
+        autoscale: local
+  -
+    file: test-data/test.vcf
+    ext: vcf
+    label: "Variant Test"
+    category: "Sequencing Data"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+  -
+    file: test-data/blast.xml
+    ext: blastxml
+    label: "BlastP Hits"
+    category: "Comparative Genomics"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+        parent: test-data/merlin.gff
+        protein: true
+        min_gap: 10
+        match: true
+  -
+    file: test-data/xmfa.gff
+    ext: gff3
+    label: "Progressive Mauve comparison"
+    category: "Comparative Genomics"
+    options:
+        __unused__: "Not used...just to ensure options has at least one key"
+        match: true
b
diff -r 2c9e5136b416 -r 497c6bb3b717 tool_dependencies.xml
--- a/tool_dependencies.xml Mon May 04 17:21:38 2015 -0400
+++ b/tool_dependencies.xml Thu Jun 18 12:10:51 2015 -0400
b
@@ -3,4 +3,16 @@
   <package name="jbrowse" version="1.11.6">
     <repository changeset_revision="d5ab749c9e97" name="package_jbrowse_1_11_6" owner="iuc" toolshed="https://toolshed.g2.bx.psu.edu" />
   </package>
+  <package name="python" version="2.7">
+    <repository changeset_revision="44bb4258922f" name="package_python_2_7" owner="iuc" toolshed="https://toolshed.g2.bx.psu.edu" />
+  </package>
+  <package name="perl" version="5.18">
+    <repository changeset_revision="114b6af405fa" name="package_perl_5_18" owner="iuc" toolshed="https://toolshed.g2.bx.psu.edu" />
+  </package>
+  <package name="samtools" version="1.2">
+    <repository changeset_revision="6eea04363026" name="package_samtools_1_2" owner="iuc" toolshed="https://toolshed.g2.bx.psu.edu" />
+  </package>
+  <package name="bundle_jbrowse" version="1.0">
+    <repository changeset_revision="361f7cf7a442" name="package_perl_bundle_jbrowse_1_0" owner="iuc" toolshed="https://toolshed.g2.bx.psu.edu" />
+  </package>
 </tool_dependency>