Repository 'jbrowse2'
hg clone https://toolshed.g2.bx.psu.edu/repos/fubar/jbrowse2

Changeset 46:4181e97c70a7 (2024-03-04)
Previous changeset 45:0ec526d2d8c1 (2024-03-01) Next changeset 47:3e53204c2419 (2024-03-06)
Commit message:
planemo upload for repository https://github.com/usegalaxy-eu/temporary-tools/tree/master/jbrowse2 commit 3a43e9e0ffce0966101203102e769d1ced28618a
modified:
__pycache__/jbrowse2.cpython-310.pyc
autogenJB2.py
autogenJB2.xml
jb2_webserver.py
jbrowse2.py
jbrowse2.xml
macros.xml
readme.rst
test-data/gff3/merlin.gff3
test-data/vcf/merlin.vcf
added:
klBraLanc5.haps_combined.decontam.20230620.fasta.fa.gz
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 __pycache__/jbrowse2.cpython-310.pyc
b
Binary file __pycache__/jbrowse2.cpython-310.pyc has changed
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 autogenJB2.py
--- a/autogenJB2.py Fri Mar 01 05:15:41 2024 +0000
+++ b/autogenJB2.py Mon Mar 04 09:47:19 2024 +0000
[
b'@@ -1,5 +1,6 @@\n import argparse\n import logging\n+import os\n import sys\n \n from jbrowse2 import JbrowseConnector as jbC\n@@ -11,8 +12,7 @@\n def makeDefaultLocation():\n \n     refName = jc.genome_firstcontig\n-    defloc  = "%s:100..10000" % refName\n-    print (\'defloc\',defloc)\n+    defloc = "%s:100..10000" % refName\n     return defloc\n \n \n@@ -21,61 +21,66 @@\n     parser.add_argument("--sessName", help="Session name", default="AutoJBrowse")\n     parser.add_argument(\n         "--trackmeta",\n-        help="Repeatable of \'filename, filext,filepath, ... ,\' for JBrowse2 tracks",\n+        help="Repeatable \'filename,filext,filepath,[bai/crai path for filesystem bam/cram]\' for JBrowse2 tracks",\n         default=[],\n         action="append",\n     )\n     parser.add_argument(\n         "--referencemeta",\n-        help="Repeatable \'filename, filext, filepath, ... ,\' for JBrowse2 reference tracks",\n+        help="Repeatable \'filename, filext, filepath, ... ,\' for JBrowse2 reference tracks - usually only one needed",\n         default=[],\n         action="append",\n     )\n     parser.add_argument(\n         "--pafmeta",\n-        help="Repeatable. Each is a \'filename, filext, filepath, ... ,\' for a JBrowse2 paf track",\n+        help="Repeatable. Each is a \'pafname, filext, filepath, ... ,\' for a JBrowse2 paf track",\n         default=[],\n         action="append",\n     )\n     parser.add_argument(\n         "--pafreferencemeta",\n-        help="Repeatable. Each is a \'pafname,filepath,refname,filepath,refname....\'. Every paf must have a corresponding one ",\n+        help="Repeatable. Each is a \'pafname,refpath,refname\' Every pafname must have one or more",\n         default=[],\n         action="append",\n     )\n-    parser.add_argument("--jbrowse2path", help="Path to JBrowse2 directory in biocontainer or Conda")\n+    parser.add_argument(\n+        "--jbrowse2path", help="Path to JBrowse2 directory in biocontainer or Conda"\n+    )\n     parser.add_argument("--outdir", help="Output directory", required=True)\n     parser.add_argument("--version", "-V", action="version", version="%(prog)s 2.10.2")\n     args = parser.parse_args()\n     sessName = args.sessName\n     # --trackmeta $jbrowseme[$key],$jbrowseme[$key].ext,\'$key\'\n-    trackList = [x.strip().split(",") for x in args.trackmeta if x > \'\']\n-    refList = [x.strip().split(",") for x in args.referencemeta if x > \'\']\n-    print("tracklist = %s\\nreflist = %s" % (trackList,refList))\n+    trackList = [x.strip().split(",") for x in args.trackmeta if x > ""]\n+    refList = [x.strip().split(",") for x in args.referencemeta if x > ""]\n     if len(refList) > 0:\n-        listgenomes = [f for f in refList if f[1] in [\'fasta\', \'fasta.gz\']]\n+        listgenomes = [f for f in refList if f[1] in ["fasta", "fasta.gz"]]\n         # assume no pafs here\n-        print(\'genomes=%s\' % listgenomes)\n         if len(listgenomes) > 0:\n-            genome_paths = [\n-                x[0] for x in listgenomes\n-            ]  # expect genome_1_genomename.fasta etc\n+            genome_paths = [x[0] for x in listgenomes]\n             genome_names = [x[2] for x in listgenomes]\n+            guseuri = []\n+            for x in genome_paths:\n+                if x.startswith(\'http://\') or x.startswith(\'https://\'):\n+                    guseuri.append(\'yes\')\n+                else:\n+                    guseuri.append(\'no\')\n             jc = jbC(\n                 outdir=args.outdir,\n                 jbrowse2path=args.jbrowse2path,\n                 genomes=[\n                     {\n                         "path": x,\n-                        "meta": {\n-                            "name": genome_names[i],\n-                            "dataset_dname": genome_names[i],\n-                        },\n+                        "label": genome_names[i],\n+                        "useuri": guseuri[i],\n+                        "meta":  {"name": genome_names[i],\n+                                            "dataset_dname": genome_names[i]\n+                           '..b'== "bam":\n+                    ipath  = track[3]\n+                    if not os.path.exists(ipath):\n+                        ipath = os.path.realpath(os.path.join(jc.outdir, trackname + \'.bai\'))\n+                        cmd = ["samtools", "index", "-b", "-o", ipath, os.path.realpath(track[0])]\n+                        sys.stdout.write(\'#### calling %s\' % \' \'.join(cmd))\n+                        jc.subprocess_check_call(cmd)\n+                    track_conf = {"conf": {"options": {"bam": {"bam_index": ipath}}}}\n+                elif trext == "cram":\n+                    ipath  = track[3]\n+                    if not os.path.exists(ipath):\n+                        jc.logging.info(\'calling %s\' % \' \'.join(cmd))\n+                        ipath = os.path.realpath(os.path.join(\'./\', trackname + \'.crai\'))\n+                        cmd = ["samtools", "index", "-c", "-o", ipath, os.path.realpath(track[0])]\n+                        sys.stdout.write(\'#### calling %s\' % \' \'.join(cmd))\n+                        jc.subprocess_check_call(cmd)\n+                    track_conf = {"conf": {"options": {"cram": {"cram_index": ipath}}}}\n                 else:\n                     track_conf = {}\n                 track_conf["format"] = trext\n                 track_conf["name"] = trackname\n                 track_conf["label"] = trackname\n-                track_conf["trackfiles"] = [(tpath, trext, trackname,{}),]\n+                useu = tpath.startswith(\'http://\') or tpath.startswith(\'https://\')\n+                useuri = \'no\'\n+                if useu:\n+                    useuri = \'yes\'\n+                track_conf["trackfiles"] = [\n+                    (tpath, trext, useuri, trackname, {}),\n+                ]\n                 track_conf["category"] = "Autogenerated"\n                 keys = jc.process_annotations(track_conf)\n \n                 if keys:\n                     for key in keys:\n-                        if trext in ["bigwig", "gff3", "gff", "vcf", "maf",]:\n+                        if trext in [\n+                            "bigwig",\n+                            "gff3",\n+                            "gff",\n+                            "vcf",\n+                            "maf",\n+                        ]:\n                             default_session_data["visibility"]["default_on"].append(key)\n                         else:\n-                            default_session_data["visibility"]["default_off"].append(key)\n-                        # if track_conf.get("style", None):\n-                        # default_session_data["style"][key] = track_conf[\n-                        # "style"\n-                        # ]  # TODO do we need this anymore?\n-                        # if track_conf.get("style_lables", None):\n-                        # default_session_data["style_labels"][key] = track_conf.get(\n-                        # "style_labels", None\n-                        # )\n+                            default_session_data["visibility"]["default_off"].append(\n+                                key\n+                            )\n             # general_data = {\n             # "analytics": root.find("metadata/general/analytics").text,\n             # "primary_color": root.find("metadata/general/primary_color").text,\n@@ -152,9 +176,13 @@\n                 jc.config_json["tracks"] = jc.tracksToAdd\n             jc.write_config()\n             defLoc = makeDefaultLocation()\n-            default_session_data.update({"defaultLocation": defLoc, "session_name": sessName})\n+            default_session_data.update(\n+                {"defaultLocation": defLoc, "session_name": sessName}\n+            )\n             track_conf.update(default_session_data)\n             jc.add_default_session(default_session_data)\n             # jc.text_index() not sure what broke here.\n     else:\n-        print("!! empty collection supplied - nothing to process")\n+        sys.stderr.write(\n+            "!!!! Collection has no suitable trackfiles for autogenJB2 - nothing to process"\n+        )\n'
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 autogenJB2.xml
--- a/autogenJB2.xml Fri Mar 01 05:15:41 2024 +0000
+++ b/autogenJB2.xml Mon Mar 04 09:47:19 2024 +0000
[
@@ -13,7 +13,17 @@
 export JBROWSE2_PATH=\$(dirname \$(which jbrowse))/../opt/jbrowse2  &&
 python '$__tool_directory__/autogenJB2.py'
 #for $key in $autoCollection.keys():
-    #if $autoCollection[$key].ext == 'fasta':
+    #if $autoCollection[$key].is_collection:
+        #set subCol=$autoCollection[$key]
+        #set pafs=[($subCol[x],$subcol[x].ext,x) for x in $subCol.keys() if $subCol[x].ext == 'paf']
+        #if len($pafs) > 0:
+             --pafmeta '$pafs[0]'
+            #set refs = [($pafs[0][2],$subCol[x],x) for x in $subCol.keys() if $subCol[x].ext == 'fasta']
+            #for $ref in $refs:
+             --pafreferencemeta '$ref'
+            #end for
+        #end if
+    #else if $autoCollection[$key].ext == 'fasta':
       --referencemeta '$autoCollection[$key],$autoCollection[$key].ext,$key'
     #else if $autoCollection[$key].ext in ['bed', 'bigwig', 'cool', 'gff', 'gff3', 'hic', 'maf', 'mcool', 'scool', 'vcf']
       --trackmeta '$autoCollection[$key],$autoCollection[$key].ext,$key'
@@ -45,23 +55,21 @@
         <data format="html" name="output" label="AutoJBrowse2"/>
     </outputs>
 <tests>
- <test>
+   <test>
       <param name="uglyTestingHack" value="enabled" />
       <param name="autoCollection">
         <collection type="list">
           <element name="Merlin" value="merlin.fa" ftype="fasta"/>
-          <element name="merlin-sample.bam" value="bam/merlin-sample.bam" ftype="bam"/>
+          <element name="test-6.bed" value="bed/test-6.bed" ftype="bed"/>
         </collection>
       </param>
-            <output name="output">
-                <assert_contents>
-                    <has_text text='"name": "Merlin",'/>
-                    <has_text text='"name": "merlin-sample.bam",'/>
-                    <has_text text='"uri": "Merlin.fa.gz.fai"'/>
-                    <has_text text='"uri": "bam_0_merlin-sample.bam.bam.bai"'/>
-
-                </assert_contents>
-            </output>
+      <output name="output">
+            <assert_contents>
+                <has_text text='"name": "Merlin",'/>
+                <has_text text='"name": "test-6.bed",'/>
+                <has_text text='"uri": "Merlin.fa.gz.fai"'/>
+            </assert_contents>
+      </output>
     </test>
 </tests>
     <help><![CDATA[
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 jb2_webserver.py
--- a/jb2_webserver.py Fri Mar 01 05:15:41 2024 +0000
+++ b/jb2_webserver.py Mon Mar 04 09:47:19 2024 +0000
b
@@ -42,7 +42,7 @@
 from http.server import SimpleHTTPRequestHandler
 
 
-DEFAULT_PORT = 8080
+DEFAULT_PORT = 8081
 
 
 def copy_byte_range(infile, outfile, start=None, stop=None, bufsize=16 * 1024):
@@ -156,7 +156,7 @@
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser(
-        description="Simple Python Web Server with Range Support"
+        description="Tiny Python Web Server supporting range requests, for local viewing of unzipped Galaxy JBrowse2 configurations"
     )
     parser.add_argument(
         "--root",
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 jbrowse2.py
--- a/jbrowse2.py Fri Mar 01 05:15:41 2024 +0000
+++ b/jbrowse2.py Mon Mar 04 09:47:19 2024 +0000
[
b'@@ -11,6 +11,7 @@\n import struct\n import subprocess\n import tempfile\n+import urllib.request\n import xml.etree.ElementTree as ET\n from collections import defaultdict\n \n@@ -446,7 +447,10 @@\n \n     def process_genomes(self):\n         assemblies = []\n+        useuri = False\n         for i, genome_node in enumerate(self.genome_paths):\n+            if genome_node["useuri"].strip().lower() == "yes":\n+                useuri = True\n             genome_name = genome_node["meta"]["dataset_dname"].strip()\n             if len(genome_name.split()) > 1:\n                 genome_name = genome_name.split()[0]\n@@ -454,7 +458,9 @@\n             if genome_name not in self.genome_names:\n                 # ignore dupes - can have multiple pafs with same references?\n                 fapath = genome_node["path"]\n-                assem = self.make_assembly(fapath, genome_name)\n+                if not useuri:\n+                    fapath = os.path.realpath(fapath)\n+                assem = self.make_assembly(fapath, genome_name, useuri)\n                 assemblies.append(assem)\n                 self.genome_names.append(genome_name)\n                 if self.genome_name is None:\n@@ -462,41 +468,67 @@\n                         genome_name  # first one for all tracks - other than paf\n                     )\n                     self.genome_firstcontig = None\n-                    fl = open(fapath, "r").readline().strip().split(">")\n-                    if len(fl) > 1:\n-                        fl = fl[1]\n-                        if len(fl.split()) > 1:\n-                            self.genome_firstcontig = fl.split()[0].strip()\n+                    if not useuri:\n+                        # https://lazarus.name/jbrowse/fish/bigwig_0_coverage_bedgraph_cov_count_count_bw.bigwig\n+                        # https://lazarus.name/jbrowse/fish/klBraLanc5.haps_combined.decontam.20230620.fasta.fa.gz\n+                        fl = open(fapath, "r").readline()\n+                        fls = fl.strip().split(">")\n+                        if len(fls) > 1:\n+                            fl = fls[1]\n+                            if len(fl.split()) > 1:\n+                                self.genome_firstcontig = fl.split()[0].strip()\n+                            else:\n+                                self.genome_firstcontig = fl\n                         else:\n-                            self.genome_firstcontig = fl\n+                            fl = urrlib.request.urlopen(faname+".fai").readline()\n+                            if fl: # is first row of the text fai so the first contig name\n+                                self.genome_firstcontig = fl.decode(\'utf8\').strip().split()[0]\n         if self.config_json.get("assemblies", None):\n             self.config_json["assemblies"] += assemblies\n         else:\n             self.config_json["assemblies"] = assemblies\n \n-    def make_assembly(self, fapath, gname):\n+    def make_assembly(self, fapath, gname, useuri):\n+        if useuri:\n+            faname = fapath\n+            adapter = {\n+                "type": "BgzipFastaAdapter",\n+                "fastaLocation": {\n+                    "uri": faname,\n+                    "locationType": "UriLocation",\n+                },\n+                "faiLocation": {\n+                    "uri": faname + ".fai",\n+                    "locationType": "UriLocation",\n+                },\n+                "gziLocation": {\n+                    "uri": faname + ".gzi",\n+                    "locationType": "UriLocation",\n+                },\n+            }\n+        else:\n+            faname = gname + ".fa.gz"\n+            fadest = os.path.realpath(os.path.join(self.outdir, faname))\n+            cmd = "bgzip -i -c %s -I %s.gzi > %s && samtools faidx %s" % (\n+                fapath,\n+                fadest,\n+                fadest,\n+                fadest,\n+            )\n+            self.subprocess_popen(cmd)\n \n-        faname = gname + ".fa.gz"\n-        fadest = os.path.realpath(os.path.join(self.outdir, faname)'..b'21,6 +1280,7 @@\n             "assemblyName": self.genome_name,\n             "start": 0,\n             "end": 100000,\n+            "refName": "x",\n         }\n \n         if data.get("defaultLocation", ""):\n@@ -1307,9 +1367,9 @@\n             json.dump(self.config_json, config_file, indent=2)\n \n     def clone_jbrowse(self):\n-        """Clone a JBrowse directory into a destination directory. This also works in Biocontainer testing now """\n+        """Clone a JBrowse directory into a destination directory. This also works in Biocontainer testing now"""\n         dest = self.outdir\n-        #self.subprocess_check_call([\'jbrowse\', \'create\', dest, \'--tag\', f"{JB_VER}"])\n+        # self.subprocess_check_call([\'jbrowse\', \'create\', dest, \'--tag\', f"{JB_VER}"])\n         shutil.copytree(self.jbrowse2path, dest, dirs_exist_ok=True)\n         for fn in [\n             "asset-manifest.json",\n@@ -1341,7 +1401,9 @@\n if __name__ == "__main__":\n     parser = argparse.ArgumentParser(description="", epilog="")\n     parser.add_argument("--xml", help="Track Configuration")\n-    parser.add_argument("--jbrowse2path", help="Path to JBrowse2 directory in biocontainer or Conda")\n+    parser.add_argument(\n+        "--jbrowse2path", help="Path to JBrowse2 directory in biocontainer or Conda"\n+    )\n     parser.add_argument("--outdir", help="Output directory", default="out")\n     parser.add_argument("--version", "-V", action="version", version="%(prog)s 2.0.1")\n     args = parser.parse_args()\n@@ -1360,7 +1422,9 @@\n         jbrowse2path=args.jbrowse2path,\n         genomes=[\n             {\n-                "path": os.path.realpath(x.attrib["path"]),\n+                "path": x.attrib["path"],\n+                "label": x.attrib["label"],\n+                "useuri": x.attrib["useuri"],\n                 "meta": metadata_from_node(x.find("metadata")),\n             }\n             for x in root.findall("metadata/genomes/genome")\n@@ -1395,10 +1459,12 @@\n         trackfiles = track.findall("files/trackFile")\n         if trackfiles:\n             for x in track.findall("files/trackFile"):\n+                track_conf["useuri"] = x.attrib["useuri"]\n                 if is_multi_bigwig:\n                     multi_bigwig_paths.append(\n                         (\n                             x.attrib["label"],\n+                            x.attrib["useuri"],\n                             os.path.realpath(x.attrib["path"]),\n                         )\n                     )\n@@ -1406,14 +1472,23 @@\n                     if trackfiles:\n                         metadata = metadata_from_node(x.find("metadata"))\n                         track_conf["dataset_id"] = metadata["dataset_id"]\n-                        track_conf["trackfiles"].append(\n-                            (\n-                                os.path.realpath(x.attrib["path"]),\n+                        if x.attrib["useuri"].lower() == "yes":\n+                            tfa = (\n+                                x.attrib["path"],\n                                 x.attrib["ext"],\n+                                x.attrib["useuri"],\n                                 x.attrib["label"],\n                                 metadata,\n                             )\n-                        )\n+                        else:\n+                            tfa = (\n+                                os.path.realpath(x.attrib["path"]),\n+                                x.attrib["ext"],\n+                                x.attrib["useuri"],\n+                                x.attrib["label"],\n+                                metadata,\n+                            )\n+                        track_conf["trackfiles"].append(tfa)\n \n         if is_multi_bigwig:\n             metadata = metadata_from_node(x.find("metadata"))\n@@ -1447,7 +1522,6 @@\n         except TypeError:\n             track_conf["style"] = {}\n             pass\n-        track_conf["conf"] = etree_to_dict(track.find("options"))\n         keys = jc.process_annotations(track_conf)\n \n         if keys:\n'
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 jbrowse2.xml
--- a/jbrowse2.xml Fri Mar 01 05:15:41 2024 +0000
+++ b/jbrowse2.xml Mon Mar 04 09:47:19 2024 +0000
[
b'@@ -1,4 +1,4 @@\n- <tool id="jbrowse2" name="jbrowse2" version="@TOOL_VERSION@+@WRAPPER_VERSION@_5" profile="22.05">\n+ <tool id="jbrowse2" name="jbrowse2" version="@TOOL_VERSION@+@WRAPPER_VERSION@_6" profile="22.05">\n     <description>genome browser</description>\n     <macros>\n         <import>macros.xml</import>\n@@ -17,35 +17,75 @@\n \n export JBROWSE2_PATH=\\$(dirname \\$(which jbrowse))/../opt/jbrowse2  &&\n \n-## Once that\'s done, we run the python script to handle the real work\n-python \'$__tool_directory__/jbrowse2.py\'\n---jbrowse2path \\${JBROWSE2_PATH}\n---outdir \'$output.files_path\'\n---xml \'$trackxml\' &&\n-#if $jbgen.zipOut == "true":\n-    (cd \'$output.files_path\' && zip -r - . ) > \'$output\'\n-#else\n-  cp \'$output.files_path/index.html\' \'$output\'\n-#end if\n-## Ugly testing hack since I cannot get <extra_files> to test the files I want to test. Hmph.\n-#if str($uglyTestingHack) == "enabled":\n- &&   cp \'$trackxml\' \'$output\'\n+#if $jbgen.ucol.formcoll=="collect":\n+    python \'$__tool_directory__/autogenJB2.py\'\n+    #for $key in $autoCollection.keys():\n+        #if $autoCollection[$key].is_collection:\n+            #set subCol=$autoCollection[$key]\n+            #set pafs=[($subCol[x],$subcol[x].ext,x) for x in $subCol.keys() if $subCol[x].ext == \'paf\']\n+            #if len($pafs) > 0:\n+                 --pafmeta \'$pafs[0]\'\n+                #set refs = [($pafs[0][2],$subCol[x],x) for x in $subCol.keys() if $subCol[x].ext == \'fasta\']\n+                #for $ref in $refs:\n+                 --pafreferencemeta \'$ref\'\n+                #end for\n+            #end if\n+        #else if $autoCollection[$key].ext == \'fasta\':\n+          --referencemeta \'$autoCollection[$key],$autoCollection[$key].ext,$key\'\n+        #else if $autoCollection[$key].ext in [\'bed\', \'bigwig\', \'cool\', \'gff\', \'gff3\', \'hic\', \'maf\', \'mcool\', \'scool\', \'vcf\']\n+          --trackmeta \'$autoCollection[$key],$autoCollection[$key].ext,$key\'\n+        #else if $autoCollection[$key].ext in [\'bam\',]\n+          --trackmeta \'$autoCollection[$key],$autoCollection[$key].ext,$key,$autoCollection[$key].metadata.bam_index\'\n+         #else if $autoCollection[$key].ext in [\'cram\',]\n+          --trackmeta \'$autoCollection[$key],$autoCollection[$key].ext,$key,$autoCollection[$key].metadata.cram_index\'\n+        #end if\n+    #end for\n+    --outdir \'$output.files_path\'\n+    --jbrowse2path \\${JBROWSE2_PATH}\n+    --sessName "Autogen JBrowse" &&\n+    #if $jbgen.zipOut == "true":\n+        (cd \'$output.files_path\' && zip -r - . ) > \'$output\'\n+    #else\n+      cp \'$output.files_path/index.html\' \'$output\'\n+    #end if\n+#else:\n+    python \'$__tool_directory__/jbrowse2.py\'\n+    --jbrowse2path \\${JBROWSE2_PATH}\n+    --outdir \'$output.files_path\'\n+    --xml \'$trackxml\' &&\n+    #if $jbgen.zipOut == "true":\n+        (cd \'$output.files_path\' && zip -r - . ) > \'$output\'\n+    #else\n+      cp \'$output.files_path/index.html\' \'$output\'\n+    #end if\n+    ## Ugly testing hack since I cannot get <extra_files> to test the files I want to test. Hmph.\n+    #if str($uglyTestingHack) == "enabled":\n+       &&   cp \'$trackxml\' \'$output\'\n+    #end if\n #end if\n   ]]></command>\n <configfiles>\n         <configfile name="trackxml"><![CDATA[<?xml version="1.0"?>\n+#if $jbgen.ucol.formcoll=="form":\n <root>\n     <metadata>\n         <genomes>\n-            #if str($reference_genome.genome_type_select) == "indexed":\n-              <genome path="${reference_genome.genome.fields.path}" label="${reference_genome.genome.fields.name}">\n+            #if str($reference_genome.genome_type_select) == "uri":\n+              <genome path="${reference_genome.uri}" label="${reference_genome.refname}" useuri="yes">\n                   <metadata>\n                      <dataset\n-                      dname = "${reference_genome.genome.name}" />\n+                      dname = "${reference_genome.refname}" />\n+              </metadata>\n+              </genome>\n+            #else if str($reference_genome.genome_type_select) == "indexed":\n+              <genome pa'..b'               <param name="annotation" value="gff3/A.gff"/>\n+                       <conditional name="useuri">\n+                            <param name="annotation" value="gff3/A.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="false"/>\n                         </conditional>\n@@ -571,7 +659,10 @@\n                 <repeat name="data_tracks">\n                     <conditional name="data_format">\n                         <param name="data_format_select" value="gene_calls"/>\n-                        <param name="annotation" value="gff3/1.gff"/>\n+                        <conditional name="useuri">\n+                            <param name="annotation" value="gff3/1.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="false"/>\n                         </conditional>\n@@ -602,7 +693,10 @@\n                 <repeat name="data_tracks">\n                     <conditional name="data_format">\n                         <param name="data_format_select" value="gene_calls"/>\n-                        <param name="annotation" value="gff3/interpro.gff"/>\n+                        <conditional name="useuri">\n+                            <param name="annotation" value="gff3/interpro.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="false"/>\n                         </conditional>\n@@ -619,7 +713,10 @@\n                 <repeat name="data_tracks">\n                     <conditional name="data_format">\n                         <param name="data_format_select" value="gene_calls"/>\n-                        <param name="annotation" value="gff3/2.gff"/>\n+                         <conditional name="useuri">\n+                            <param name="annotation" value="gff3/2.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="true"/>\n                             <param name="name" value="cDNA_match"/>\n@@ -659,7 +756,10 @@\n                 <repeat name="data_tracks">\n                     <conditional name="data_format">\n                         <param name="data_format_select" value="gene_calls"/>\n-                        <param name="annotation" value="gff3/1.gff"/>\n+                        <conditional name="useuri">\n+                            <param name="annotation" value="gff3/1.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="false"/>\n                         </conditional>\n@@ -691,7 +791,11 @@\n                 <repeat name="data_tracks">\n                     <conditional name="data_format">\n                         <param name="data_format_select" value="gene_calls"/>\n-                        <param name="annotation" value="gff3/1.gff"/>\n+                         <conditional name="useuri">\n+                            <param name="annotation" value="gff3/1.gff"/>\n+                            <param name="insource" value= "history"/>\n+                        </conditional>\n+                        <param name="insource" value= "history"/>\n                         <conditional name="match_part">\n                             <param name="match_part_select" value="false"/>\n                         </conditional>\n'
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 klBraLanc5.haps_combined.decontam.20230620.fasta.fa.gz
b
Binary file klBraLanc5.haps_combined.decontam.20230620.fasta.fa.gz has changed
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 macros.xml
--- a/macros.xml Fri Mar 01 05:15:41 2024 +0000
+++ b/macros.xml Mon Mar 04 09:47:19 2024 +0000
[
@@ -140,6 +140,19 @@
 
     <xml name="general_options">
         <section name="jbgen" title="General JBrowse Options [Advanced]" expanded="false">
+            <conditional name="ucol">
+                <param name="formcoll" type="select" label="Convert a collection of track files rather than filling in the tool form"
+                    help="A collection of bam/vcf and other track types will be converted into a JBrowse2 automatically">
+                    <option value="form" selected="true">Fill in the tool form to specify tracks for the output JBrowse2</option>
+                    <option value="collect">Convert a collection of suitable track files</option>
+                </param>
+                <when value="collect">
+                       <param label="Collection of bed, bam and other track files" name="autoCollection" type="data_collection" />
+                </when>
+                <when value="form">
+                </when>
+            </conditional>
+
             <param label="Create a zip archive for downloading rather than viewing " name="zipOut" help="Default is to make an interactive browser appear when the 'eye' icon is activated"
             type="boolean" checked="false" truevalue="true" falsevalue="false" />
             <param label="Subset to display to new users" type="text" name="defaultLocation" value="" help="Initial subset to be shown for users who have never visited the browser before. Example: 'ctgA:1234..5678'"/>
@@ -505,8 +518,27 @@
     </xml>
 
     <xml name="input_conditional" token_label="Track Data" token_format="data">
-        <param label="@LABEL@" format="@FORMAT@" name="annotation" optional="True" type="data" multiple="True"/>
-    </xml>
+        <conditional name="useuri">
+                <param name="insource" type="select" label="Define track data as a history file or an internet URI"
+                    help="A public URI implies that all the associated tabix files are also in place. They are created for history files">
+                    <option value="history" selected="true">Track data from a history file</option>
+                    <option value="uri" selected="true">Tabix data URI - index files must be available at corresponding URI</option>
+                </param>
+                <when value="history">
+                       <param label="@LABEL@" format="@FORMAT@" name="annotation" multiple="True" optional="true" type="data" />
+                </when>
+                <when value="uri">
+                       <param label="@LABEL@" name="annouri" multiple="false" type="text" />
+                       <param label="Short name for track display" name="annoname" type="text" >
+                             <sanitizer invalid_char="_">
+                                <valid initial="string.printable" >
+                                    <remove value="'" />
+                                </valid>
+                              </sanitizer>
+                        </param>
+                </when>
+            </conditional>
+     </xml>
     <xml name="citations">
         <citations>
         <citation type="doi">10.1186/s13059-016-0924-1</citation>
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 readme.rst
--- a/readme.rst Fri Mar 01 05:15:41 2024 +0000
+++ b/readme.rst Mon Mar 04 09:47:19 2024 +0000
b
@@ -1,7 +1,19 @@
 JBrowse2 in Galaxy
 ==================
 
-Added Feb 3: cool/mcool -> hic 
+Added Mar 3:
+- optional tracks at last for JB2
+    - dotted noodles from optional inputs now ignored without harm
+- autogenJB2.
+    - Takes a collection of bam/vcf etc and turns them into tracks in a normal JB2 history item.
+    - Uses the JbrowseConnector, but the XML tool drives it from the contents of the collection.
+    - Collection can be built from any source or with optional noodles in a WF
+    - Produces a JB2 with all available tracks.
+    - Argparse command line with repeats for tracks and references
+        - so works outside Galaxy to process directories or s3 buckets.
+
+
+Added Feb 3: cool/mcool -> hic
 
 .. image:: dm4_in_jb2.png
 
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 test-data/gff3/merlin.gff3
--- a/test-data/gff3/merlin.gff3 Fri Mar 01 05:15:41 2024 +0000
+++ b/test-data/gff3/merlin.gff3 Mon Mar 04 09:47:19 2024 +0000
b
b'@@ -1,1230 +1,38 @@\n ##gff-version 3\n ##sequence-region Merlin 1 172788\n-Merlin  GeneMark.hmm    gene    2   691 -856.563659 +   .   ID=Merlin_1;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    2   691 .   +   .   ID=Merlin_1_mRNA;Parent=Merlin_1;seqid=Merlin;color=#00ff00\n-Merlin  GeneMark.hmm    exon    2   691 .   +   .   ID=Merlin_1_exon;Parent=Merlin_1_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 2   691 .   +   0   ID=Merlin_1_CDS;Parent=Merlin_1_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    752 1039    -339.046618 +   .   ID=Merlin_2;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    752 1039    .   +   .   ID=Merlin_2_mRNA;Parent=Merlin_2;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    752 1039    .   +   .   ID=Merlin_2_exon;Parent=Merlin_2_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 752 1039    .   +   0   ID=Merlin_2_CDS;Parent=Merlin_2_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    1067    2011    -1229.683915    -   .   ID=Merlin_3;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    1067    2011    .   -   .   ID=Merlin_3_mRNA;Parent=Merlin_3;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    1067    2011    .   -   .   ID=Merlin_3_exon;Parent=Merlin_3_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 1067    2011    .   -   0   ID=Merlin_3_CDS;Parent=Merlin_3_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    2011    3066    -1335.034872    -   .   ID=Merlin_4;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    2011    3066    .   -   .   ID=Merlin_4_mRNA;Parent=Merlin_4;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    2011    3066    .   -   .   ID=Merlin_4_exon;Parent=Merlin_4_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 2011    3066    .   -   0   ID=Merlin_4_CDS;Parent=Merlin_4_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    3066    4796    -2177.374893    -   .   ID=Merlin_5;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    3066    4796    .   -   .   ID=Merlin_5_mRNA;Parent=Merlin_5;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    3066    4796    .   -   .   ID=Merlin_5_exon;Parent=Merlin_5_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 3066    4796    .   -   0   ID=Merlin_5_CDS;Parent=Merlin_5_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    4793    5317    -682.565030 -   .   ID=Merlin_6;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    4793    5317    .   -   .   ID=Merlin_6_mRNA;Parent=Merlin_6;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    4793    5317    .   -   .   ID=Merlin_6_exon;Parent=Merlin_6_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 4793    5317    .   -   0   ID=Merlin_6_CDS;Parent=Merlin_6_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    5289    6431    -1457.525863    -   .   ID=Merlin_7;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    5289    6431    .   -   .   ID=Merlin_7_mRNA;Parent=Merlin_7;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    5289    6431    .   -   .   ID=Merlin_7_exon;Parent=Merlin_7_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 5289    6431    .   -   0   ID=Merlin_7_CDS;Parent=Merlin_7_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    6428    7180    -968.015933 -   .   ID=Merlin_8;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    6428    7180    .   -   .   ID=Merlin_8_mRNA;Parent=Merlin_8;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    6428    7180    .   -   .   ID=Merlin_8_exon;Parent=Merlin_8_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 6428    7180    .   -   0   ID=Merlin_8_CDS;Parent=Merlin_8_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    7228    7857    -809.330137 +   .   ID=Merlin_9;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    7228    7857    .   +   .   ID=Merlin_9_mRNA;Parent=Merlin_9;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    7228    7857    .   +   .   ID=Merlin_9_exon;Parent=Merlin_9_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 7228    7857    .   +   0   ID=Merlin_9_CDS;Parent=Merlin_9_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    7857    8252    -515.006678 +   .   ID=Merlin_10;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    7857    8252    .   +   .   ID=Merlin'..b'20.159549 +   .   ID=Merlin_305;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    168941  169120  .   +   .   ID=Merlin_305_mRNA;Parent=Merlin_305;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    168941  169120  .   +   .   ID=Merlin_305_exon;Parent=Merlin_305_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 168941  169120  .   +   0   ID=Merlin_305_CDS;Parent=Merlin_305_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    169175  171265  -2617.092758    +   .   ID=Merlin_306;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    169175  171265  .   +   .   ID=Merlin_306_mRNA;Parent=Merlin_306;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    169175  171265  .   +   .   ID=Merlin_306_exon;Parent=Merlin_306_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 169175  171265  .   +   0   ID=Merlin_306_CDS;Parent=Merlin_306_exon;seqid=Merlin\n-Merlin  GeneMark.hmm    gene    171301  172788  -1876.322043    +   .   ID=Merlin_307;seqid=Merlin\n-Merlin  GeneMark.hmm    mRNA    171301  172788  .   +   .   ID=Merlin_307_mRNA;Parent=Merlin_307;seqid=Merlin\n-Merlin  GeneMark.hmm    exon    171301  172788  .   +   .   ID=Merlin_307_exon;Parent=Merlin_307_mRNA;seqid=Merlin\n-Merlin  GeneMark.hmm    CDS 171301  172788  .   +   0   ID=Merlin_307_CDS;Parent=Merlin_307_exon;seqid=Merlin\n+Merlin  GeneMark.hmm    gene    10  30  .   +   .   ID=Merlin_1;seqid=Merlin\n+Merlin  GeneMark.hmm    mRNA    14  30  .   +   .   ID=Merlin_1_mRNA;Parent=Merlin_1\n+Merlin  GeneMark.hmm    CDS 14  20  1000    +   0   ID=Merlin_1_CDS ;Parent=Merlin_1_mRNA\n+Merlin  GeneMark.hmm    CDS 24  30  500 +   0   ID=Merlin_1_CDS ;Parent=Merlin_1_mRNA\n+Merlin  GeneMark.hmm    gene    14  30  .   +   .   ID=Merlin_2;seqid=Merlin;color=#00ff00\n+Merlin  GeneMark.hmm    mRNA    14  30  .   +   .   ID=Merlin_2_mRNA;seqid=Merlin;color=#00ff00;Parent=Merlin_2\n+Merlin  GeneMark.hmm    CDS 14  20  500 +   0   ID=Merlin_2_CDS ;Parent=Merlin_2_mRNA;color=#0000ff\n+Merlin  GeneMark.hmm    CDS 24  30  750 +   0   ID=Merlin_2_CDS ;Parent=Merlin_2_mRNA;color=#00ff00\n+Merlin  GeneMark.hmm    gene    10  30  .   +   .   ID=Merlin_3;seqid=Merlin\n+Merlin  GeneMark.hmm    mRNA    14  30  .   +   .   ID=Merlin_3A_mRNA;Parent=Merlin_3;color=#0000ff\n+Merlin  GeneMark.hmm    CDS 14  18  1000    +   0   ID=Merlin_3A_CDS ;Parent=Merlin_3A_mRNA;color=#0000ff\n+Merlin  GeneMark.hmm    CDS 20  30  800 +   0   ID=Merlin_3A_CDS ;Parent=Merlin_3A_mRNA;color=#0000ff\n+Merlin  GeneMark.hmm    mRNA    14  30  .   +   .   ID=Merlin_3B_mRNA;Parent=Merlin_3;color=#0000ff\n+Merlin  GeneMark.hmm    CDS 14  22  400 +   0   ID=Merlin_3B_CDS ;Parent=Merlin_3B_mRNA;color=#0000ff\n+Merlin  GeneMark.hmm    CDS 24  30  1000    +   0   ID=Merlin_3B_CDS ;Parent=Merlin_3B_mRNA;color=#0000ff\n+Merlin  exonerate   gene    1740    2300    .   +   .   Name=Apple3;Note=Gene with two splicing models;ID=1\n+Merlin  exonerate   mRNA    1740    2300    .   +   .   Name=Apple3-a;Note=mRNA A with both CDSs and UTRs;ID=1A;Parent=1;\n+Merlin  exonerate   UTR 1740    1799    .   +   .   Parent=1A\n+Merlin  exonerate   CDS 1900    2080    .   +   0   Parent=1A\n+Merlin  exonerate   CDS 2100    2120    .   +   2   Parent=1A\n+Merlin  exonerate   UTR 2120    2300    .   +   .   Parent=1A\n+Merlin  exonerate   mRNA    1740    2300    .   +   .   Name=Apple3-b;Note=mRNA B with both CDSs and UTRs;ID=1B;Parent=1;\n+Merlin  exonerate   UTR 1740    1799    .   +   .   Parent=1B\n+Merlin  exonerate   CDS 1800    1880    .   +   0   Parent=1B\n+Merlin  exonerate   CDS 1900    1950    .   +   1   Parent=1B\n+Merlin  exonerate   CDS 2100    2120    .   +   2   Parent=1B\n+Merlin  exonerate   UTR 2120    2300    .   +   .   Parent=1B\n+#    {\n+#    "baseUrl": "http://localhost:8000/out/data/"\n+#    "compress": 0,\n+#    "label": "Transcript",\n+#    "storeClass": "JBrowse/Store/SeqFeature/NCList",\n+#    "trackType": "JBrowse/View/Track/CanvasFeatures",\n+#    "type": "JBrowse/View/Track/CanvasFeatures",\n+#    "urlTemplate": "tracks/42ff9cb16c0509f0abb4a76ce14077bc_0/{refseq}/trackData.json",\n+#    }\n'
b
diff -r 0ec526d2d8c1 -r 4181e97c70a7 test-data/vcf/merlin.vcf
--- a/test-data/vcf/merlin.vcf Fri Mar 01 05:15:41 2024 +0000
+++ b/test-data/vcf/merlin.vcf Mon Mar 04 09:47:19 2024 +0000
b
@@ -3,21 +3,21 @@
 ##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">
+##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  170   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  1020   .   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  3445 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  5050 .   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  20000 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
+##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 170 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 1020 . 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 3445 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 5050 . 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 20000 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