# HG changeset patch
# User fubar
# Date 1711942902 0
# Node ID 3b2815efa5d9570446bbe0c2210876f4b87cbf00
# Parent 2bdb748df0988cc84c96c42f211905915faca990
planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/jbrowse2 commit b361309b05a861da9b64e1324157a8c32767e0bf
diff -r 2bdb748df098 -r 3b2815efa5d9 config.json
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config.json Mon Apr 01 03:41:42 2024 +0000
@@ -0,0 +1,9 @@
+{
+ "assemblies": [],
+ "configuration": {},
+ "connections": [],
+ "defaultSession": {
+ "name": "New Session"
+ },
+ "tracks": []
+}
\ No newline at end of file
diff -r 2bdb748df098 -r 3b2815efa5d9 jbrowse2.py
--- a/jbrowse2.py Sat Mar 30 22:33:29 2024 +0000
+++ b/jbrowse2.py Mon Apr 01 03:41:42 2024 +0000
@@ -8,6 +8,7 @@
import os
import re
import shutil
+import ssl
import struct
import subprocess
import tempfile
@@ -39,6 +40,32 @@
}
+INDEX_TEMPLATE = """
+
+
+
+
+
+
+
+
+JBrowse
+
+
+
+
+
+
+"""
+
+
class ColorScaling(object):
COLOR_FUNCTION_TEMPLATE = """
@@ -376,6 +403,9 @@
def __init__(self, outdir, jbrowse2path):
self.assemblies = [] # these require more than a few line diff.
self.assmeta = {}
+ self.ass_first_contigs = (
+ []
+ ) # for default session - these are read as first line of the assembly .fai
self.giURL = GALAXY_INFRASTRUCTURE_URL
self.outdir = outdir
self.jbrowse2path = jbrowse2path
@@ -451,6 +481,22 @@
}
return wstyle
+ def urllib_get_2018():
+ # Using a protected member like this is not any more fragile
+ # than extending the class and using it. I would use it.
+ url = "https://localhost:6667/my-endpoint"
+ ssl._create_default_https_context = ssl._create_unverified_context
+ with urllib.request.urlopen(url=url) as f:
+ print(f.read().decode("utf-8"))
+
+ def urllib_get_2022():
+ # Finally! Able to use the publice API. Happy happy!
+ url = "https://localhost:6667/my-endpoint"
+ scontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
+ scontext.verify_mode = ssl.VerifyMode.CERT_NONE
+ with urllib.request.urlopen(url=url, context=scontext) as f:
+ print(f.read().decode("utf-8"))
+
def process_genomes(self, genomes):
assembly = []
assmeta = []
@@ -469,8 +515,9 @@
fapath = genome_node["path"]
if not useuri:
fapath = os.path.realpath(fapath)
- assem = self.make_assembly(fapath, genome_name, useuri)
+ assem, first_contig = self.make_assembly(fapath, genome_name, useuri)
assembly.append(assem)
+ self.ass_first_contigs.append(first_contig)
if len(genome_names) == 0:
this_genome["genome_name"] = genome_name # first one for all tracks
genome_names.append(genome_name)
@@ -491,7 +538,12 @@
this_genome["genome_firstcontig"] = fl
else:
try:
- fl = urllib.request.urlopen(fapath + ".fai").readline()
+ scontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
+ scontext.verify_mode = ssl.VerifyMode.CERT_NONE
+ with urllib.request.urlopen(
+ url=fapath + ".fai", context=scontext
+ ) as f:
+ fl = f.readline()
except Exception:
fl = None
if fl: # is first row of the text fai so the first contig name
@@ -506,6 +558,9 @@
return this_genome["genome_name"]
def make_assembly(self, fapath, gname, useuri):
+ """added code to grab the first contig name and length for broken default session from Anthony and Helena's code
+ that poor Bjoern is trying to figure out.
+ """
if useuri:
faname = fapath
adapter = {
@@ -514,6 +569,12 @@
"faiLocation": {"uri": faname + ".fai", "locationType": "UriLocation"},
"gziLocation": {"uri": faname + ".gzi", "locationType": "UriLocation"},
}
+ scontext = ssl.SSLContext(ssl.PROTOCOL_TLS)
+ scontext.verify_mode = ssl.VerifyMode.CERT_NONE
+ with urllib.request.urlopen(url=faname + ".fai", context=scontext) as f:
+ fl = f.readline()
+ contig = fl.decode("utf8").strip()
+ # Merlin 172788 8 60 61
else:
faname = gname + ".fa.gz"
fadest = os.path.realpath(os.path.join(self.outdir, faname))
@@ -537,7 +598,9 @@
"uri": faname + ".gzi",
},
}
-
+ contig = open(fadest + ".fai", "r").readline().strip()
+ first_contig = contig.split()[:2]
+ first_contig.insert(0, gname)
trackDict = {
"name": gname,
"sequence": {
@@ -556,7 +619,7 @@
},
],
}
- return trackDict
+ return (trackDict, first_contig)
def add_default_view(self):
cmd = [
@@ -907,7 +970,6 @@
else:
cpath = os.path.realpath(dest) + ".crai"
cmd = ["samtools", "index", "-c", "-o", cpath, os.path.realpath(dest)]
- logging.debug("executing cmd %s" % " ".join(cmd))
self.subprocess_check_call(cmd)
trackDict = {
"type": "AlignmentsTrack",
@@ -1136,7 +1198,7 @@
if gname not in self.genome_names:
# ignore if already there - eg for duplicates among pafs.
- asstrack = self.make_assembly(pgpaths[i], gname, useuri)
+ asstrack, first_contig = self.make_assembly(pgpaths[i], gname, useuri)
self.genome_names.append(gname)
self.tracksToAdd[gname] = []
self.assemblies.append(asstrack)
@@ -1318,7 +1380,7 @@
for track_conf in self.tracksToAdd[gnome]:
tId = track_conf["trackId"]
track_types[tId] = track_conf["type"]
- style_data = default_data["style"].get(tId, None)
+ style_data = default_data[gnome]["style"].get(tId, None)
if not style_data:
logging.debug(
"### No style data in default data %s for %s"
@@ -1393,6 +1455,75 @@
with open(self.config_json_file, "w") as config_file:
json.dump(self.config_json, config_file, indent=2)
+ def add_defsess_to_index(self, data):
+ """
+ Broken in Anthony's PR because only ever dealt with the first assembly.
+
+ Add some default session settings: set some assemblies/tracks on/off
+
+ This allows to select a default view:
+ - jb type (Linear, Circular, etc)
+ - default location on an assembly
+ - default tracks
+ - ...
+
+ Different methods to do that were tested/discussed:
+ - using a defaultSession item in config.json: this proved to be difficult:
+ forced to write a full session block, including hard-coded/hard-to-guess items,
+ no good way to let Jbrowse2 display a scaffold without knowing its size
+ - using JBrowse2 as an embedded React component in a tool-generated html file:
+ it works but it requires generating js code to actually do what we want = chosing default view, assembly, tracks, ...
+ - writing a session-spec inside the config.json file: this is not yet supported as of 2.10.2 (see PR 4148 below)
+ a session-spec is a kind of simplified defaultSession where you don't need to specify every aspect of the session
+ - passing a session-spec through URL params by embedding the JBrowse2 index.html inside an iframe
+ we selected this option
+
+ Xrefs to understand the choices:
+ https://github.com/GMOD/jbrowse-components/issues/2708
+ https://github.com/GMOD/jbrowse-components/discussions/3568
+ https://github.com/GMOD/jbrowse-components/pull/4148
+ """
+ new_index = "Nothing written"
+ session_spec = {"views": []}
+ logging.debug("def data=%s" % data)
+ for first_contig in self.ass_first_contigs:
+ gnome, refName, end = first_contig
+ start = 0
+ if False or data.get("defaultLocation", ""):
+ loc_match = re.search(
+ r"^([^:]+):([\d,]*)\.*([\d,]*)$", data["defaultLocation"]
+ )
+ # loc_match = re.search(r"^(\w+):(\d+)\.+(\d+)$", data["defaultLocation"])
+ if loc_match:
+ refName = loc_match.group(1)
+ start = int(loc_match.group(2))
+ end = int(loc_match.group(3))
+ else:
+ if refName:
+ view = {
+ "assembly": gnome,
+ "loc": "{}:{}-{}".format(refName, start, end),
+ "type": "LinearGenomeView",
+ "tracks": data[gnome]["tracks"],
+ }
+ session_spec["views"].append(view)
+ sess = json.dumps(session_spec, sort_keys=True, indent=2)
+ new_index = INDEX_TEMPLATE.replace(
+ "__SESSION_SPEC__", "&session=spec-{}".format(sess)
+ )
+
+ os.rename(
+ os.path.join(self.outdir, "index.html"),
+ os.path.join(self.outdir, "index_noview.html"),
+ )
+
+ with open(os.path.join(self.outdir, "index.html"), "w") as nind:
+ nind.write(new_index)
+ logging.debug(
+ "#### add_defsession gnome=%s refname=%s\nsession_spec=%s\nnew_index=%s"
+ % (gnome, refName, sess, new_index)
+ )
+
def add_general_configuration(self, data):
"""
Add some general configuration to the config.json file
@@ -1426,7 +1557,7 @@
with open(config_path, "w") as config_file:
json.dump(self.config_json, config_file, indent=2)
- def clone_jbrowse(self, realclone=True):
+ def clone_jbrowse(self, realclone=False):
"""Clone a JBrowse directory into a destination directory. This also works in Biocontainer testing now
Leave as True between version updates on temporary tools - requires manual conda trigger :(
"""
@@ -1480,14 +1611,7 @@
jc = JbrowseConnector(outdir=args.outdir, jbrowse2path=args.jbrowse2path)
- default_session_data = {
- "visibility": {
- "default_on": [],
- "default_off": [],
- },
- "style": {},
- "style_labels": {},
- }
+ default_session_data = {}
for ass in root.findall("assembly"):
genomes = [
@@ -1500,7 +1624,16 @@
for x in ass.findall("metadata/genomes/genome")
]
assref_name = jc.process_genomes(genomes)
-
+ if not default_session_data.get(assref_name, None):
+ default_session_data[assref_name] = {
+ "tracks": [],
+ "style": {},
+ "style_labels": {},
+ "visibility": {
+ "default_on": [],
+ "default_off": [],
+ },
+ }
for track in ass.find("tracks"):
track_conf = {}
track_conf["trackfiles"] = []
@@ -1577,21 +1710,22 @@
vis = track.attrib.get("visibility", "default_off")
if not vis:
vis = "default_off"
- default_session_data["visibility"][vis].append(key)
+ default_session_data[assref_name]["visibility"][vis].append(key)
if track.find("options/style"):
- default_session_data["style"][key] = {
+ default_session_data[assref_name]["style"][key] = {
item.tag: parse_style_conf(item)
for item in track.find("options/style")
}
else:
- default_session_data["style"][key] = {}
- logging.debug("@@@@ no options/style found for %s" % (key))
+ default_session_data[assref_name]["style"][key] = {}
+ logging.debug("no options/style found for %s" % (key))
if track.find("options/style_labels"):
- default_session_data["style_labels"][key] = {
+ default_session_data[assref_name]["style_labels"][key] = {
item.tag: parse_style_conf(item)
for item in track.find("options/style_labels")
}
+ default_session_data[assref_name]["tracks"].append(key)
default_session_data["defaultLocation"] = root.find(
"metadata/general/defaultLocation"
).text
@@ -1616,7 +1750,8 @@
assconf = jc.config_json.get("assemblies", [])
assconf += jc.assemblies
jc.config_json["assemblies"] = assconf
- logging.debug("&&&assemblies=%s, gnames=%s" % (assconf, jc.genome_names))
+ logging.debug("assemblies=%s, gnames=%s" % (assconf, jc.genome_names))
jc.write_config()
jc.add_default_session(default_session_data)
+ jc.add_defsess_to_index(default_session_data)
# jc.text_index() not sure what broke here.
diff -r 2bdb748df098 -r 3b2815efa5d9 jbrowse2.xml
--- a/jbrowse2.xml Sat Mar 30 22:33:29 2024 +0000
+++ b/jbrowse2.xml Mon Apr 01 03:41:42 2024 +0000
@@ -1,4 +1,4 @@
-
+
genome browser
macros.xml