Mercurial > repos > fubar > jbrowse2
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"], |
