comparison jbrowse2.py @ 127:fbabf7498471 draft

planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/jbrowse2 commit 116b1a4bbd62251ad552306df2dc8aa8f46c6721
author fubar
date Mon, 07 Oct 2024 02:11:55 +0000
parents 160f33c6ba85
children fce4ed3b1702
comparison
equal deleted inserted replaced
126:fd0fc6fdc7c5 127:fbabf7498471
359 # exit early 359 # exit early
360 return metadata 360 return metadata
361 except Exception: 361 except Exception:
362 return {} 362 return {}
363 363
364 for (key, value) in node.findall("dataset")[0].attrib.items(): 364 for key, value in node.findall("dataset")[0].attrib.items():
365 metadata["dataset_%s" % key] = value 365 metadata["dataset_%s" % key] = value
366 366
367 if node.findall("history"): 367 if node.findall("history"):
368 for (key, value) in node.findall("history")[0].attrib.items(): 368 for key, value in node.findall("history")[0].attrib.items():
369 metadata["history_%s" % key] = value 369 metadata["history_%s" % key] = value
370 370
371 if node.findall("metadata"): 371 if node.findall("metadata"):
372 for (key, value) in node.findall("metadata")[0].attrib.items(): 372 for key, value in node.findall("metadata")[0].attrib.items():
373 metadata["metadata_%s" % key] = value 373 metadata["metadata_%s" % key] = value
374 # Additional Mappings applied: 374 # Additional Mappings applied:
375 metadata[ 375 metadata["dataset_edam_format"] = (
376 "dataset_edam_format" 376 '<a target="_blank" href="http://edamontology.org/{0}">{1}</a>'.format(
377 ] = '<a target="_blank" href="http://edamontology.org/{0}">{1}</a>'.format( 377 metadata["dataset_edam_format"], metadata["dataset_file_ext"]
378 metadata["dataset_edam_format"], metadata["dataset_file_ext"] 378 )
379 ) 379 )
380 metadata["history_user_email"] = '<a href="mailto:{0}">{0}</a>'.format( 380 metadata["history_user_email"] = '<a href="mailto:{0}">{0}</a>'.format(
381 metadata["history_user_email"] 381 metadata["history_user_email"]
382 ) 382 )
383 metadata["hist_name"] = metadata["history_display_name"] 383 metadata["hist_name"] = metadata["history_display_name"]
384 metadata[ 384 metadata["history_display_name"] = (
385 "history_display_name" 385 '<a target="_blank" href="{galaxy}/history/view/{encoded_hist_id}">{hist_name}</a>'.format(
386 ] = '<a target="_blank" href="{galaxy}/history/view/{encoded_hist_id}">{hist_name}</a>'.format( 386 galaxy=GALAXY_INFRASTRUCTURE_URL,
387 galaxy=GALAXY_INFRASTRUCTURE_URL, 387 encoded_hist_id=metadata.get("history_id", "not available"),
388 encoded_hist_id=metadata.get("history_id", "not available"), 388 hist_name=metadata.get("history_display_name", "not available"),
389 hist_name=metadata.get("history_display_name", "not available"), 389 )
390 ) 390 )
391 if node.findall("tool"): 391 if node.findall("tool"):
392 for (key, value) in node.findall("tool")[0].attrib.items(): 392 for key, value in node.findall("tool")[0].attrib.items():
393 metadata["tool_%s" % key] = value 393 metadata["tool_%s" % key] = value
394 metadata[ 394 metadata["tool_tool"] = (
395 "tool_tool" 395 '<a target="_blank" href="{galaxy}/datasets/{encoded_id}/show_params">{tool_id}{tool_version}</a>'.format(
396 ] = '<a target="_blank" href="{galaxy}/datasets/{encoded_id}/show_params">{tool_id}{tool_version}</a>'.format( 396 galaxy=GALAXY_INFRASTRUCTURE_URL,
397 galaxy=GALAXY_INFRASTRUCTURE_URL, 397 encoded_id=metadata.get("dataset_id", ""),
398 encoded_id=metadata.get("dataset_id", ""), 398 tool_id=metadata.get("tool_tool_id", ""),
399 tool_id=metadata.get("tool_tool_id", ""), 399 tool_version=metadata.get("tool_tool_version", ""),
400 tool_version=metadata.get("tool_tool_version", ""), 400 )
401 ) 401 )
402 return metadata 402 return metadata
403 403
404 404
405 class JbrowseConnector(object): 405 class JbrowseConnector(object):
617 with open(self.config_json_file, "w") as fp: 617 with open(self.config_json_file, "w") as fp:
618 json.dump(self.config_json, fp, indent=2) 618 json.dump(self.config_json, fp, indent=2)
619 619
620 def text_index(self): 620 def text_index(self):
621 # Index tracks 621 # Index tracks
622 args = [ 622 args = ["jbrowse", "text-index"]
623 "jbrowse",
624 "text-index"
625 ]
626 self.subprocess_check_call(args) 623 self.subprocess_check_call(args)
627 624
628 def add_hic(self, data, trackData): 625 def add_hic(self, data, trackData):
629 """ 626 """
630 HiC adapter. 627 HiC adapter.
674 ], 671 ],
675 "category": [ 672 "category": [
676 categ, 673 categ,
677 ], 674 ],
678 "adapter": {"type": "HicAdapter", "hicLocation": {"uri": uri}}, 675 "adapter": {"type": "HicAdapter", "hicLocation": {"uri": uri}},
679
680 } 676 }
681 self.tracksToAdd[trackData["assemblyNames"]].append(copy.copy(trackDict)) 677 self.tracksToAdd[trackData["assemblyNames"]].append(copy.copy(trackDict))
682 self.trackIdlist.append(tId) 678 self.trackIdlist.append(tId)
683 679
684 def add_maf(self, data, trackData): 680 def add_maf(self, data, trackData):
1125 style_json = self._prepare_track_style(trackDict) 1121 style_json = self._prepare_track_style(trackDict)
1126 trackDict["style"] = style_json 1122 trackDict["style"] = style_json
1127 if self.config_json.get("plugins", None): 1123 if self.config_json.get("plugins", None):
1128 self.config_json["plugins"].append(bedPlugin) 1124 self.config_json["plugins"].append(bedPlugin)
1129 else: 1125 else:
1130 self.config_json["plugins"] = [bedPlugin,] 1126 self.config_json["plugins"] = [
1127 bedPlugin,
1128 ]
1131 self.tracksToAdd[trackData["assemblyNames"]].append(copy.copy(trackDict)) 1129 self.tracksToAdd[trackData["assemblyNames"]].append(copy.copy(trackDict))
1132 self.trackIdlist.append(tId) 1130 self.trackIdlist.append(tId)
1133 1131
1134 def add_paf(self, data, trackData, pafOpts, **kwargs): 1132 def add_paf(self, data, trackData, pafOpts, **kwargs):
1135 tname = trackData["name"] 1133 tname = trackData["name"]
1136 tId = trackData["label"] 1134 tId = trackData["label"]
1137 url = tId 1135 url = tId
1136 usePIF = False # much faster if indexed remotely or locally
1138 useuri = data.startswith("http://") or data.startswith("https://") 1137 useuri = data.startswith("http://") or data.startswith("https://")
1139 if not useuri: 1138 if not useuri:
1140 dest = os.path.join(self.outdir, url) 1139 dest = os.path.join(self.outdir, url)
1141 self.symlink_or_copy(os.path.realpath(data), dest) 1140 self.symlink_or_copy(os.path.realpath(data), dest)
1141 cmd = ["jbrowse", "make-pif", dest]
1142 self.subprocess_check_call(cmd)
1143 usePIF = True
1144 url = '%s.pif.gz' % tId
1142 nrow = self.getNrow(dest) 1145 nrow = self.getNrow(dest)
1143 else: 1146 else:
1144 url = data 1147 url = data
1145 nrow = self.getNrow(url) 1148 if data.endswith(".pif.gz") or data.endswith(".paf.gz"): # is tabix
1149 usePIF = True
1150 nrow = 1
1151 else:
1152 nrow = self.getNrow(url)
1146 categ = trackData["category"] 1153 categ = trackData["category"]
1147 pg = pafOpts["genome"].split(",") 1154 pg = pafOpts["genome"].split(",")
1148 pgc = [x.strip() for x in pg if x.strip() > ""] 1155 pgc = [x.strip() for x in pg if x.strip() > ""]
1149 gnomes = [x.split(" ~ ") for x in pgc] 1156 gnomes = [x.split(" ~ ") for x in pgc]
1150 logging.debug("pg=%s, gnomes=%s" % (pg, gnomes)) 1157 logging.debug("pg=%s, gnomes=%s" % (pg, gnomes))
1173 "assemblyNames": passnames, 1180 "assemblyNames": passnames,
1174 "category": [ 1181 "category": [
1175 categ, 1182 categ,
1176 ], 1183 ],
1177 "name": tname, 1184 "name": tname,
1178 "adapter": { 1185 "displays": [
1186 {
1187 "type": "LGVSyntenyDisplay",
1188 "displayId": "%s-LGVSyntenyDisplay" % tId,
1189 },
1190 {
1191 "type": "DotplotDisplay",
1192 "displayId": "%s-DotplotDisplay" % tId,
1193 },
1194 {
1195 "type": "LinearComparativeDisplay",
1196 "displayId": "%s-LinearComparativeDisplay" % tId,
1197 },
1198 {
1199 "type": "LinearBasicDisplay",
1200 "displayId": "%s-LinearSyntenyDisplay" % tId,
1201 },
1202 ],
1203 }
1204 if usePIF:
1205 trackDict["adapter"] = {
1206 "type": "PairwiseIndexedPAFAdapter",
1207 "pifGzLocation": {"uri": url},
1208 "assemblyNames": passnames,
1209 "index": {
1210 "location": {
1211 "uri": url + ".tbi",
1212 }
1213 },
1214 }
1215 else:
1216 trackDict["adapter"] = {
1179 "type": "PAFAdapter", 1217 "type": "PAFAdapter",
1180 "pafLocation": {"uri": url}, 1218 "pafLocation": {"uri": url},
1181 "assemblyNames": passnames, 1219 "assemblyNames": passnames,
1182 }, 1220 }
1183 "displays": [ 1221 if (not usePIF) and (nrow > 10000):
1184 {
1185 "type": "LGVSyntenyDisplay",
1186 "displayId": "%s-LGVSyntenyDisplay" % tId,
1187 },
1188 {
1189 "type": "DotplotDisplay",
1190 "displayId": "%s-DotplotDisplay" % tId,
1191 },
1192 {
1193 "type": "LinearComparativeDisplay",
1194 "displayId": "%s-LinearComparativeDisplay" % tId,
1195 },
1196 {
1197 "type": "LinearBasicDisplay",
1198 "displayId": "%s-LinearSyntenyDisplay" % tId,
1199 },
1200 ],
1201 }
1202 if nrow > 10000:
1203 style_json = { 1222 style_json = {
1204 "type": "LGVSyntenyDisplay", 1223 "type": "LGVSyntenyDisplay",
1205 "displayId": "%s-LGVSyntenyDisplay" % tId, 1224 "displayId": "%s-LGVSyntenyDisplay" % tId,
1206 } 1225 }
1207 else: 1226 else:
1334 default session settings are hard and fragile. 1353 default session settings are hard and fragile.
1335 .add_default_view() and other configuration code adapted from 1354 .add_default_view() and other configuration code adapted from
1336 https://github.com/abretaud/tools-iuc/blob/jbrowse2/tools/jbrowse2/jbrowse2.py 1355 https://github.com/abretaud/tools-iuc/blob/jbrowse2/tools/jbrowse2/jbrowse2.py
1337 """ 1356 """
1338 # TODO using the default session for now, but check out session specs in the future https://github.com/GMOD/jbrowse-components/issues/2708 1357 # TODO using the default session for now, but check out session specs in the future https://github.com/GMOD/jbrowse-components/issues/2708
1339 bpPerPx = self.bpPerPx # Browser window width is unknown and default session cannot be used to figure it out in JB2 code so could be 200-2000+ pixels. 1358 bpPerPx = (
1359 self.bpPerPx
1360 ) # Browser window width is unknown and default session cannot be used to figure it out in JB2 code so could be 200-2000+ pixels.
1340 track_types = {} 1361 track_types = {}
1341 with open(self.config_json_file, "r") as config_file: 1362 with open(self.config_json_file, "r") as config_file:
1342 config_json = json.load(config_file) 1363 config_json = json.load(config_file)
1343 if self.config_json: 1364 if self.config_json:
1344 config_json.update(self.config_json) 1365 config_json.update(self.config_json)
1359 logging.debug( 1380 logging.debug(
1360 "No style data for %s in available default data %s" 1381 "No style data for %s in available default data %s"
1361 % (tId, default_data) 1382 % (tId, default_data)
1362 ) 1383 )
1363 else: 1384 else:
1364 logging.debug( 1385 logging.debug("style data for %s = %s" % (tId, style_data))
1365 "style data for %s = %s" 1386 if style_data.get("type", None) is None:
1366 % (tId, style_data)
1367 )
1368 if style_data.get('type', None) is None:
1369 style_data["type"] = "LinearBasicDisplay" 1387 style_data["type"] = "LinearBasicDisplay"
1370 if "displays" in track_conf: 1388 if "displays" in track_conf:
1371 disp = track_conf["displays"][0]["type"] 1389 disp = track_conf["displays"][0]["type"]
1372 style_data["type"] = disp 1390 style_data["type"] = disp
1373 if track_conf.get("displays", None): 1391 if track_conf.get("displays", None):
1374 style_data["configuration"] = track_conf["displays"][0]["displayId"] 1392 style_data["configuration"] = track_conf["displays"][0][
1393 "displayId"
1394 ]
1375 else: 1395 else:
1376 logging.debug("no display in track_conf for %s" % tId) 1396 logging.debug("no display in track_conf for %s" % tId)
1377 if track_conf.get("style_labels", None): 1397 if track_conf.get("style_labels", None):
1378 # TODO fix this: it should probably go in a renderer block (SvgFeatureRenderer) but still does not work 1398 # TODO fix this: it should probably go in a renderer block (SvgFeatureRenderer) but still does not work
1379 # TODO move this to per track displays? 1399 # TODO move this to per track displays?
1416 view_json = { 1436 view_json = {
1417 "type": "LinearGenomeView", 1437 "type": "LinearGenomeView",
1418 "offsetPx": 0, 1438 "offsetPx": 0,
1419 "bpPerPx": bpPerPx, 1439 "bpPerPx": bpPerPx,
1420 "minimized": False, 1440 "minimized": False,
1421 "tracks": tracks_data 1441 "tracks": tracks_data,
1422 } 1442 }
1423 if drdict.get("refName", None): 1443 if drdict.get("refName", None):
1424 # TODO displayedRegions is not just zooming to the region, it hides the rest of the chromosome 1444 # TODO displayedRegions is not just zooming to the region, it hides the rest of the chromosome
1425 view_json["displayedRegions"] = [ 1445 view_json["displayedRegions"] = [
1426 drdict, 1446 drdict,
1537 with open(config_path, "w") as config_file: 1557 with open(config_path, "w") as config_file:
1538 json.dump(self.config_json, config_file, indent=2) 1558 json.dump(self.config_json, config_file, indent=2)
1539 1559
1540 def clone_jbrowse(self, realclone=False): 1560 def clone_jbrowse(self, realclone=False):
1541 """ 1561 """
1542 Clone a JBrowse directory into a destination directory. 1562 Clone a JBrowse directory into a destination directory.
1543 1563
1544 `realclone=true` will use the `jbrowse create` command. 1564 `realclone=true` will use the `jbrowse create` command.
1545 To allow running on internet-less compute and for reproducibility 1565 To allow running on internet-less compute and for reproducibility
1546 use frozen code with `realclone=false 1566 use frozen code with `realclone=false
1547 1567
1548 """ 1568 """
1549 dest = self.outdir 1569 dest = self.outdir
1550 if (not os.path.exists(self.jbrowse2path)) or realclone: 1570 if (not os.path.exists(self.jbrowse2path)) or realclone:
1551 self.subprocess_check_call( 1571 self.subprocess_check_call(
1568 else: 1588 else:
1569 os.remove(path) 1589 os.remove(path)
1570 except OSError as e: 1590 except OSError as e:
1571 log.error("Error: %s - %s." % (e.filename, e.strerror)) 1591 log.error("Error: %s - %s." % (e.filename, e.strerror))
1572 for neededfile in ["jb2_webserver.py", "bedscoreplugin.js"]: 1592 for neededfile in ["jb2_webserver.py", "bedscoreplugin.js"]:
1573 shutil.copyfile(os.path.join(INSTALLED_TO, neededfile), os.path.join(dest, neededfile)) 1593 shutil.copyfile(
1594 os.path.join(INSTALLED_TO, neededfile), os.path.join(dest, neededfile)
1595 )
1574 1596
1575 1597
1576 def parse_style_conf(item): 1598 def parse_style_conf(item):
1577 if item.text.lower() in ["false", "true", "yes", "no"]: 1599 if item.text.lower() in ["false", "true", "yes", "no"]:
1578 return item.text.lower in ("yes", "true") 1600 return item.text.lower in ("yes", "true")
1590 parser.add_argument("--outdir", help="Output directory", default="out") 1612 parser.add_argument("--outdir", help="Output directory", default="out")
1591 parser.add_argument("--version", "-V", action="version", version=JB2VER) 1613 parser.add_argument("--version", "-V", action="version", version=JB2VER)
1592 args = parser.parse_args() 1614 args = parser.parse_args()
1593 tree = ET.parse(args.xml) 1615 tree = ET.parse(args.xml)
1594 root = tree.getroot() 1616 root = tree.getroot()
1595 removeMe = string.punctuation.replace('.', ' ').replace('/', '').replace('-', '') 1617 removeMe = string.punctuation.replace(".", " ").replace("/", "").replace("-", "")
1596 # first is a space because space needs to be added here for removal from labels as paths. 1618 # first is a space because space needs to be added here for removal from labels as paths.
1597 nopunct = str.maketrans(dict.fromkeys(removeMe)) 1619 nopunct = str.maketrans(dict.fromkeys(removeMe))
1598 # This should be done ASAP 1620 # This should be done ASAP
1599 GALAXY_INFRASTRUCTURE_URL = root.find("metadata/galaxyUrl").text 1621 GALAXY_INFRASTRUCTURE_URL = root.find("metadata/galaxyUrl").text
1600 # Sometimes this comes as `localhost` without a protocol 1622 # Sometimes this comes as `localhost` without a protocol
1644 1666
1645 trackfiles = track.findall("files/trackFile") 1667 trackfiles = track.findall("files/trackFile")
1646 if trackfiles: 1668 if trackfiles:
1647 for x in trackfiles: 1669 for x in trackfiles:
1648 isBed = False 1670 isBed = False
1649 if x.attrib['ext'] == "bed": 1671 if x.attrib["ext"] == "bed":
1650 isBed = True 1672 isBed = True
1651 track_conf["label"] = "%s_%d" % ( 1673 track_conf["label"] = "%s_%d" % (
1652 x.attrib["label"].translate(nopunct), 1674 x.attrib["label"].translate(nopunct),
1653 trackI, 1675 trackI,
1654 ) 1676 )
1662 os.path.realpath(x.attrib["path"]), 1684 os.path.realpath(x.attrib["path"]),
1663 ) 1685 )
1664 ) 1686 )
1665 else: 1687 else:
1666 metadata = metadata_from_node(x.find("metadata")) 1688 metadata = metadata_from_node(x.find("metadata"))
1667 track_conf["dataset_id"] = metadata.get( 1689 track_conf["dataset_id"] = metadata.get("dataset_id", "None")
1668 "dataset_id", "None"
1669 )
1670 if x.attrib["useuri"].lower() == "yes": 1690 if x.attrib["useuri"].lower() == "yes":
1671 tfa = ( 1691 tfa = (
1672 x.attrib["path"], 1692 x.attrib["path"],
1673 x.attrib["ext"], 1693 x.attrib["ext"],
1674 x.attrib["useuri"], 1694 x.attrib["useuri"],