Mercurial > repos > fubar > jbrowse2
comparison jbrowse2.py @ 97:74074746ccd8 draft
planemo upload for repository https://github.com/usegalaxy-eu/temporary-tools/tree/master/jbrowse2 commit 1c04ea76330d0148a7682b3c26846e5a5df21f99
author | fubar |
---|---|
date | Sat, 01 Jun 2024 05:37:13 +0000 |
parents | 4c517a0041a8 |
children | b1260bca5fdc |
comparison
equal
deleted
inserted
replaced
96:5ef1ba2031f2 | 97:74074746ccd8 |
---|---|
20 log = logging.getLogger("jbrowse") | 20 log = logging.getLogger("jbrowse") |
21 | 21 |
22 JB2VER = "v2.11.0" | 22 JB2VER = "v2.11.0" |
23 # version pinned if cloning - but not cloning now | 23 # version pinned if cloning - but not cloning now |
24 logCommands = True | 24 logCommands = True |
25 # useful for seeing what's being written but not for production setups | 25 # useful for seeing what's being written but NOT for production setups |
26 TODAY = datetime.datetime.now().strftime("%Y-%m-%d") | 26 TODAY = datetime.datetime.now().strftime("%Y-%m-%d") |
27 SELF_LOCATION = os.path.dirname(os.path.realpath(__file__)) | 27 SELF_LOCATION = os.path.dirname(os.path.realpath(__file__)) |
28 GALAXY_INFRASTRUCTURE_URL = None | 28 GALAXY_INFRASTRUCTURE_URL = None |
29 mapped_chars = { | 29 mapped_chars = { |
30 ">": "__gt__", | 30 ">": "__gt__", |
37 "}": "__cc__", | 37 "}": "__cc__", |
38 "@": "__at__", | 38 "@": "__at__", |
39 "#": "__pd__", | 39 "#": "__pd__", |
40 "": "__cn__", | 40 "": "__cn__", |
41 } | 41 } |
42 | |
43 | |
44 INDEX_TEMPLATE = """<!doctype html> | |
45 <html lang="en" style="height:100%"> | |
46 <head> | |
47 <meta charset="utf-8"/> | |
48 <link rel="shortcut icon" href="./favicon.ico"/> | |
49 <meta name="viewport" content="width=device-width,initial-scale=1"/> | |
50 <meta name="theme-color" content="#000000"/> | |
51 <meta name="description" content="A fast and flexible genome browser"/> | |
52 <link rel="manifest" href="./manifest.json"/> | |
53 <title>JBrowse</title> | |
54 </script> | |
55 </head> | |
56 <body style="overscroll-behavior:none; height:100%; margin: 0;"> | |
57 <iframe | |
58 id="jbframe" | |
59 title="JBrowse2" | |
60 frameborder="0" | |
61 width="100%" | |
62 height="100%" | |
63 src='index_noview.html?config=config.json__SESSION_SPEC__'> | |
64 </iframe> | |
65 </body> | |
66 </html> | |
67 """ | |
68 | 42 |
69 | 43 |
70 class ColorScaling(object): | 44 class ColorScaling(object): |
71 | 45 |
72 COLOR_FUNCTION_TEMPLATE = """ | 46 COLOR_FUNCTION_TEMPLATE = """ |
489 if not useuri: | 463 if not useuri: |
490 fl = open(url, "r").readlines() | 464 fl = open(url, "r").readlines() |
491 nrow = len(fl) | 465 nrow = len(fl) |
492 else: | 466 else: |
493 try: | 467 try: |
494 scontext = ssl.SSLContext(ssl.PROTOCOL_TLS) | 468 scontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
469 scontext.check_hostname = False | |
495 scontext.verify_mode = ssl.VerifyMode.CERT_NONE | 470 scontext.verify_mode = ssl.VerifyMode.CERT_NONE |
496 with urllib.request.urlopen(url, context=scontext) as f: | 471 with urllib.request.urlopen(url, context=scontext) as f: |
497 fl = f.readlines() | 472 fl = f.readlines() |
498 nrow = len(fl) | 473 nrow = len(fl) |
499 except Exception: | 474 except Exception: |
542 """added code to grab the first contig name and length for broken default session from Anthony and Helena's code | 517 """added code to grab the first contig name and length for broken default session from Anthony and Helena's code |
543 that poor Bjoern is trying to figure out. | 518 that poor Bjoern is trying to figure out. |
544 """ | 519 """ |
545 if useuri: | 520 if useuri: |
546 faname = fapath | 521 faname = fapath |
547 scontext = ssl.SSLContext(ssl.PROTOCOL_TLS) | 522 scontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
523 scontext.check_hostname = False | |
548 scontext.verify_mode = ssl.VerifyMode.CERT_NONE | 524 scontext.verify_mode = ssl.VerifyMode.CERT_NONE |
549 with urllib.request.urlopen(url=faname + ".fai", context=scontext) as f: | 525 with urllib.request.urlopen(url=faname + ".fai", context=scontext) as f: |
550 fl = f.readline() | 526 fl = f.readline() |
551 contig = fl.decode("utf8").strip() | 527 contig = fl.decode("utf8").strip() |
552 # Merlin 172788 8 60 61 | 528 # Merlin 172788 8 60 61 |
895 gsa = self.assmeta.get(trackData["assemblyNames"], None) | 871 gsa = self.assmeta.get(trackData["assemblyNames"], None) |
896 if gsa: | 872 if gsa: |
897 genseqad = gsa[0]["genome_sequence_adapter"] | 873 genseqad = gsa[0]["genome_sequence_adapter"] |
898 else: | 874 else: |
899 genseqad = "Not found" | 875 genseqad = "Not found" |
900 logging.warn("No adapter found for cram %s in gsa=%s" % (tId, gsa)) | 876 logging.warning("No adapter found for cram %s in gsa=%s" % (tId, gsa)) |
901 if useuri: | 877 if useuri: |
902 url = data | 878 url = data |
903 else: | 879 else: |
904 fname = tId | 880 fname = tId |
905 dest = os.path.join(self.outdir, fname) | 881 dest = os.path.join(self.outdir, fname) |
963 useuri = trackData["useuri"].lower() == "yes" | 939 useuri = trackData["useuri"].lower() == "yes" |
964 if useuri: | 940 if useuri: |
965 url = data | 941 url = data |
966 else: | 942 else: |
967 url = tId | 943 url = tId |
968 dest = "%s/%s" % (self.outdir, url) | 944 dest = os.path.join(self.outdir, url) |
969 cmd = "bgzip -c %s > %s" % (data, dest) | 945 cmd = "bgzip -c %s > %s" % (data, dest) |
970 self.subprocess_popen(cmd) | 946 self.subprocess_popen(cmd) |
971 cmd = ["tabix", "-f", "-p", "vcf", dest] | 947 cmd = ["tabix", "-f", "-p", "vcf", dest] |
972 self.subprocess_check_call(cmd) | 948 self.subprocess_check_call(cmd) |
973 trackDict = { | 949 trackDict = { |
1030 useuri = trackData["useuri"].lower() == "yes" | 1006 useuri = trackData["useuri"].lower() == "yes" |
1031 if useuri: | 1007 if useuri: |
1032 url = trackData["path"] | 1008 url = trackData["path"] |
1033 else: | 1009 else: |
1034 url = tId + ".gz" | 1010 url = tId + ".gz" |
1035 dest = "%s/%s" % (self.outdir, url) | 1011 dest = os.path.join(self.outdir, url) |
1036 self._sort_gff(data, dest) | 1012 self._sort_gff(data, dest) |
1037 categ = trackData["category"] | 1013 categ = trackData["category"] |
1038 trackDict = { | 1014 trackDict = { |
1039 "type": "FeatureTrack", | 1015 "type": "FeatureTrack", |
1040 "trackId": tId, | 1016 "trackId": tId, |
1076 useuri = trackData["useuri"].lower() == "yes" | 1052 useuri = trackData["useuri"].lower() == "yes" |
1077 if useuri: | 1053 if useuri: |
1078 url = data | 1054 url = data |
1079 else: | 1055 else: |
1080 url = tId + ".gz" | 1056 url = tId + ".gz" |
1081 dest = "%s/%s" % (self.outdir, url) | 1057 dest = os.path.join(self.outdir, url) |
1082 self._sort_bed(data, dest) | 1058 self._sort_bed(data, dest) |
1083 trackDict = { | 1059 trackDict = { |
1084 "type": "FeatureTrack", | 1060 "type": "FeatureTrack", |
1085 "trackId": tId, | 1061 "trackId": tId, |
1086 "name": trackData["name"], | 1062 "name": trackData["name"], |
1123 tname = trackData["name"] | 1099 tname = trackData["name"] |
1124 tId = trackData["label"] | 1100 tId = trackData["label"] |
1125 url = tId | 1101 url = tId |
1126 useuri = data.startswith("http://") or data.startswith("https://") | 1102 useuri = data.startswith("http://") or data.startswith("https://") |
1127 if not useuri: | 1103 if not useuri: |
1128 dest = "%s/%s" % (self.outdir, url) | 1104 dest = os.path.join(self.outdir, url) |
1129 self.symlink_or_copy(os.path.realpath(data), dest) | 1105 self.symlink_or_copy(os.path.realpath(data), dest) |
1130 nrow = self.getNrow(dest) | 1106 nrow = self.getNrow(dest) |
1131 else: | 1107 else: |
1132 url = data | 1108 url = data |
1133 nrow = self.getNrow(url) | 1109 nrow = self.getNrow(url) |
1325 default session settings are hard and fragile. | 1301 default session settings are hard and fragile. |
1326 .add_default_view() and other configuration code adapted from | 1302 .add_default_view() and other configuration code adapted from |
1327 https://github.com/abretaud/tools-iuc/blob/jbrowse2/tools/jbrowse2/jbrowse2.py | 1303 https://github.com/abretaud/tools-iuc/blob/jbrowse2/tools/jbrowse2/jbrowse2.py |
1328 """ | 1304 """ |
1329 # TODO using the default session for now, but check out session specs in the future https://github.com/GMOD/jbrowse-components/issues/2708 | 1305 # TODO using the default session for now, but check out session specs in the future https://github.com/GMOD/jbrowse-components/issues/2708 |
1306 bpPerPx = 50 # this is tricky since browser window width is unknown - this seems a compromise that sort of works.... | |
1330 track_types = {} | 1307 track_types = {} |
1331 with open(self.config_json_file, "r") as config_file: | 1308 with open(self.config_json_file, "r") as config_file: |
1332 config_json = json.load(config_file) | 1309 config_json = json.load(config_file) |
1333 if self.config_json: | 1310 if self.config_json: |
1334 config_json.update(self.config_json) | 1311 config_json.update(self.config_json) |
1363 "type": track_types[tId], | 1340 "type": track_types[tId], |
1364 "configuration": tId, | 1341 "configuration": tId, |
1365 "displays": [style_data], | 1342 "displays": [style_data], |
1366 } | 1343 } |
1367 ) | 1344 ) |
1368 view_json = { | |
1369 "type": "LinearGenomeView", | |
1370 "offsetPx": 0, | |
1371 "minimized": False, | |
1372 "tracks": tracks_data, | |
1373 } | |
1374 first = [x for x in self.ass_first_contigs if x[0] == gnome] | 1345 first = [x for x in self.ass_first_contigs if x[0] == gnome] |
1375 if len(first) > 0: | 1346 drdict = { |
1376 [gnome, refName, end] = first[0] | |
1377 start = 0 | |
1378 end = int(end) | |
1379 drdict = { | |
1380 "refName": refName, | |
1381 "start": start, | |
1382 "end": end, | |
1383 "reversed": False, | 1347 "reversed": False, |
1384 "assemblyName": gnome, | 1348 "assemblyName": gnome, |
1385 } | 1349 } |
1350 if len(first) > 0: | |
1351 [gnome, refName, end] = first[0] | |
1352 drdict["refName"] = refName | |
1353 drdict["start"] = 0 | |
1354 end = int(end) | |
1355 drdict["end"] = end | |
1386 else: | 1356 else: |
1387 ddl = default_data.get("defaultLocation", None) | 1357 ddl = default_data.get("defaultLocation", None) |
1388 if ddl: | 1358 if ddl: |
1389 loc_match = re.search(r"^([^:]+):([\d,]*)\.*([\d,]*)$", ddl) | 1359 loc_match = re.search(r"^([^:]+):([\d,]*)\.*([\d,]*)$", ddl) |
1390 # allow commas like 100,000 but ignore as integer | 1360 # allow commas like 100,000 but ignore as integer |
1398 else: | 1368 else: |
1399 logging.info( | 1369 logging.info( |
1400 "@@@ regexp could not match contig:start..end in the supplied location %s - please fix" | 1370 "@@@ regexp could not match contig:start..end in the supplied location %s - please fix" |
1401 % ddl | 1371 % ddl |
1402 ) | 1372 ) |
1373 view_json = { | |
1374 "type": "LinearGenomeView", | |
1375 "offsetPx": 0, | |
1376 "bpPerPx" : bpPerPx, | |
1377 "minimized": False, | |
1378 "tracks": tracks_data | |
1379 } | |
1403 if drdict.get("refName", None): | 1380 if drdict.get("refName", None): |
1404 # TODO displayedRegions is not just zooming to the region, it hides the rest of the chromosome | 1381 # TODO displayedRegions is not just zooming to the region, it hides the rest of the chromosome |
1405 view_json["displayedRegions"] = [ | 1382 view_json["displayedRegions"] = [ |
1406 drdict, | 1383 drdict, |
1407 ] | 1384 ] |
1413 session_views.append(view_json) | 1390 session_views.append(view_json) |
1414 session_name = default_data.get("session_name", "New session") | 1391 session_name = default_data.get("session_name", "New session") |
1415 for key, value in mapped_chars.items(): | 1392 for key, value in mapped_chars.items(): |
1416 session_name = session_name.replace(value, key) | 1393 session_name = session_name.replace(value, key) |
1417 session_json["name"] = session_name | 1394 session_json["name"] = session_name |
1418 | |
1419 if "views" not in session_json: | 1395 if "views" not in session_json: |
1420 session_json["views"] = session_views | 1396 session_json["views"] = session_views |
1421 else: | 1397 else: |
1422 session_json["views"] += session_views | 1398 session_json["views"] += session_views |
1423 pp = json.dumps(session_views, indent=2) | 1399 pp = json.dumps(session_views, indent=2) |
1427 with open(self.config_json_file, "w") as config_file: | 1403 with open(self.config_json_file, "w") as config_file: |
1428 json.dump(self.config_json, config_file, indent=2) | 1404 json.dump(self.config_json, config_file, indent=2) |
1429 | 1405 |
1430 def add_defsess_to_index(self, data): | 1406 def add_defsess_to_index(self, data): |
1431 """ | 1407 """ |
1432 PROBABLY NOW BROKEN by changes since this was deprecated temporarily as at April 18 | 1408 ---------------------------------------------------------- |
1433 | |
1434 Included on request of the new codeowner, from Anthony's IUC PR. | |
1435 Had to be fixed to keep each assembly with the associated tracks for a default view. | |
1436 Originally used only the first assembly, putting all tracks there and so breaking some | |
1437 when tested with 2 or more. | |
1438 | |
1439 ---------------------------------------------------------- | |
1440 Add some default session settings: set some assemblies/tracks on/off | 1409 Add some default session settings: set some assemblies/tracks on/off |
1441 | 1410 |
1442 This allows to select a default view: | 1411 This allows to select a default view: |
1443 - jb type (Linear, Circular, etc) | 1412 - jb type (Linear, Circular, etc) |
1444 - default location on an assembly | 1413 - default location on an assembly |
1459 Xrefs to understand the choices: | 1428 Xrefs to understand the choices: |
1460 https://github.com/GMOD/jbrowse-components/issues/2708 | 1429 https://github.com/GMOD/jbrowse-components/issues/2708 |
1461 https://github.com/GMOD/jbrowse-components/discussions/3568 | 1430 https://github.com/GMOD/jbrowse-components/discussions/3568 |
1462 https://github.com/GMOD/jbrowse-components/pull/4148 | 1431 https://github.com/GMOD/jbrowse-components/pull/4148 |
1463 """ | 1432 """ |
1433 | |
1434 | |
1435 INDEX_TEMPLATE = """<!doctype html> | |
1436 <html lang="en" style="height:100%"> | |
1437 <head> | |
1438 <meta charset="utf-8"/> | |
1439 <link rel="shortcut icon" href="./favicon.ico"/> | |
1440 <meta name="viewport" content="width=device-width,initial-scale=1"/> | |
1441 <meta name="theme-color" content="#000000"/> | |
1442 <meta name="description" content="A fast and flexible genome browser"/> | |
1443 <link rel="manifest" href="./manifest.json"/> | |
1444 <title>JBrowse</title> | |
1445 </script> | |
1446 </head> | |
1447 <body style="overscroll-behavior:none; height:100%; margin: 0;"> | |
1448 <iframe | |
1449 id="jbframe" | |
1450 title="JBrowse2" | |
1451 frameborder="0" | |
1452 width="100%" | |
1453 height="100%" | |
1454 src='index_noview.html?config=config.json__SESSION_SPEC__'> | |
1455 </iframe> | |
1456 </body> | |
1457 </html> | |
1458 """ | |
1459 | |
1464 new_index = "Nothing written" | 1460 new_index = "Nothing written" |
1465 session_spec = {"views": []} | 1461 session_spec = {"views": []} |
1466 logging.debug("def ass_first=%s\ndata=%s" % (self.ass_first_contigs, data)) | 1462 logging.debug("def ass_first=%s\ndata=%s" % (self.ass_first_contigs, data)) |
1467 for first_contig in self.ass_first_contigs: | 1463 for first_contig in self.ass_first_contigs: |
1468 logging.debug("first contig=%s" % self.ass_first_contigs) | 1464 logging.debug("first contig=%s" % self.ass_first_contigs) |
1542 "robots.txt", | 1538 "robots.txt", |
1543 "umd_plugin.js", | 1539 "umd_plugin.js", |
1544 "version.txt", | 1540 "version.txt", |
1545 "test_data", | 1541 "test_data", |
1546 ]: | 1542 ]: |
1547 cmd = ["rm", "-rf", os.path.join(dest, fn)] | 1543 try: |
1548 self.subprocess_check_call(cmd) | 1544 path = os.path.join(dest, fn) |
1549 cmd = ["cp", os.path.join(INSTALLED_TO, "jb2_webserver.py"), dest] | 1545 if os.path.isdir(path): |
1550 self.subprocess_check_call(cmd) | 1546 shutil.rmtree(path) |
1547 else: | |
1548 os.remove(path) | |
1549 except OSError as e: | |
1550 log.error("Error: %s - %s." % (e.filename, e.strerror)) | |
1551 shutil.copyfile(os.path.join(INSTALLED_TO, "jb2_webserver.py"), os.path.join(dest, "jb2_webserver.py")) | |
1551 | 1552 |
1552 | 1553 |
1553 def parse_style_conf(item): | 1554 def parse_style_conf(item): |
1554 if item.text.lower() in ["false", "true", "yes", "no"]: | 1555 if item.text.lower() in ["false", "true", "yes", "no"]: |
1555 return item.text.lower in ("yes", "true") | 1556 return item.text.lower in ("yes", "true") |
1559 | 1560 |
1560 if __name__ == "__main__": | 1561 if __name__ == "__main__": |
1561 parser = argparse.ArgumentParser(description="", epilog="") | 1562 parser = argparse.ArgumentParser(description="", epilog="") |
1562 parser.add_argument("--xml", help="Track Configuration") | 1563 parser.add_argument("--xml", help="Track Configuration") |
1563 parser.add_argument( | 1564 parser.add_argument( |
1564 "--jbrowse2path", help="Path to JBrowse2 directory in biocontainer or Conda" | 1565 "--jbrowse2path", help="Path to JBrowse2 directory in BioContainer or Conda" |
1565 ) | 1566 ) |
1566 parser.add_argument("--outdir", help="Output directory", default="out") | 1567 parser.add_argument("--outdir", help="Output directory", default="out") |
1567 parser.add_argument("--version", "-V", action="version", version=JB2VER) | 1568 parser.add_argument("--version", "-V", action="version", version=JB2VER) |
1568 args = parser.parse_args() | 1569 args = parser.parse_args() |
1569 tree = ET.parse(args.xml) | 1570 tree = ET.parse(args.xml) |