Mercurial > repos > fubar > jbrowse2
comparison jbrowse2.py @ 57:94264fe60478 draft
planemo upload for repository https://github.com/usegalaxy-eu/temporary-tools/tree/master/jbrowse2 commit 4b5df41484f6bdf316edaf95b53c92d328ec1674-dirty
author | fubar |
---|---|
date | Thu, 21 Mar 2024 08:01:42 +0000 |
parents | c0097a584a8a |
children | f807e219cec3 |
comparison
equal
deleted
inserted
replaced
56:c0097a584a8a | 57:94264fe60478 |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # change to accumulating all configuration for config.json based on the default from the clone | 2 # change to accumulating all configuration for config.json based on the default from the clone |
3 import argparse | 3 import argparse |
4 import binascii | 4 import binascii |
5 import datetime | 5 import datetime |
6 import json | 6 import json |
8 import os | 8 import os |
9 import re | 9 import re |
10 import shutil | 10 import shutil |
11 import struct | 11 import struct |
12 import subprocess | 12 import subprocess |
13 import sys | |
14 import tempfile | 13 import tempfile |
15 import urllib.request | 14 import urllib.request |
16 import xml.etree.ElementTree as ET | 15 import xml.etree.ElementTree as ET |
17 from collections import defaultdict | 16 from collections import defaultdict |
18 | 17 |
478 if len(fl.split()) > 1: | 477 if len(fl.split()) > 1: |
479 self.genome_firstcontig = fl.split()[0].strip() | 478 self.genome_firstcontig = fl.split()[0].strip() |
480 else: | 479 else: |
481 self.genome_firstcontig = fl | 480 self.genome_firstcontig = fl |
482 else: | 481 else: |
483 fl = urllib.request.urlopen(fapath+".fai").readline() | 482 fl = urllib.request.urlopen(fapath + ".fai").readline() |
484 if fl: # is first row of the text fai so the first contig name | 483 if fl: # is first row of the text fai so the first contig name |
485 self.genome_firstcontig = fl.decode('utf8').strip().split()[0] | 484 self.genome_firstcontig = ( |
485 fl.decode("utf8").strip().split()[0] | |
486 ) | |
486 if self.config_json.get("assemblies", None): | 487 if self.config_json.get("assemblies", None): |
487 self.config_json["assemblies"] += assemblies | 488 self.config_json["assemblies"] += assemblies |
488 else: | 489 else: |
489 self.config_json["assemblies"] = assemblies | 490 self.config_json["assemblies"] = assemblies |
490 | 491 |
536 "type": "ReferenceSequenceTrack", | 537 "type": "ReferenceSequenceTrack", |
537 "trackId": gname, | 538 "trackId": gname, |
538 "adapter": adapter, | 539 "adapter": adapter, |
539 }, | 540 }, |
540 "rendering": {"type": "DivSequenceRenderer"}, | 541 "rendering": {"type": "DivSequenceRenderer"}, |
542 "displays": [ | |
543 { | |
544 "type": "LinearReferenceSequenceDisplay", | |
545 "displayId": "%s-LinearReferenceSequenceDisplay" % gname, | |
546 }, | |
547 { | |
548 "type": "LinearGCContentDisplay", | |
549 "displayId": "%s-LinearGCContentDisplay" % gname, | |
550 }, | |
551 ], | |
541 } | 552 } |
542 return trackDict | 553 return trackDict |
543 | 554 |
544 def add_default_view(self): | 555 def add_default_view(self): |
545 cmd = [ | 556 cmd = [ |
602 useuri = trackData["useuri"].lower() == "yes" | 613 useuri = trackData["useuri"].lower() == "yes" |
603 if useuri: | 614 if useuri: |
604 uri = data | 615 uri = data |
605 else: | 616 else: |
606 uri = trackData["hic_url"] | 617 uri = trackData["hic_url"] |
607 categ = trackData['category'] | 618 categ = trackData["category"] |
608 trackDict = { | 619 trackDict = { |
609 "type": "HicTrack", | 620 "type": "HicTrack", |
610 "trackId": tId, | 621 "trackId": tId, |
611 "name": uri, | 622 "name": uri, |
612 "assemblyNames": [self.genome_name], | 623 "assemblyNames": [self.genome_name], |
613 "category": [categ,], | 624 "category": [ |
625 categ, | |
626 ], | |
614 "adapter": { | 627 "adapter": { |
615 "type": "HicAdapter", | 628 "type": "HicAdapter", |
616 "hicLocation": uri, | 629 "hicLocation": uri, |
617 }, | 630 }, |
618 "displays": [ | 631 "displays": [ |
620 "type": "LinearHicDisplay", | 633 "type": "LinearHicDisplay", |
621 "displayId": "%s-LinearHicDisplay" % tId, | 634 "displayId": "%s-LinearHicDisplay" % tId, |
622 }, | 635 }, |
623 ], | 636 ], |
624 } | 637 } |
625 style_json = self._prepare_track_style(trackDict) | |
626 trackDict["style"] = style_json | |
627 self.tracksToAdd.append(trackDict) | 638 self.tracksToAdd.append(trackDict) |
628 self.trackIdlist.append(tId) | 639 self.trackIdlist.append(tId) |
629 | 640 |
630 def add_maf(self, data, trackData): | 641 def add_maf(self, data, trackData): |
631 """ | 642 """ |
641 "name": "MafViewer", | 652 "name": "MafViewer", |
642 "url": "https://unpkg.com/jbrowse-plugin-mafviewer/dist/jbrowse-plugin-mafviewer.umd.production.min.js", | 653 "url": "https://unpkg.com/jbrowse-plugin-mafviewer/dist/jbrowse-plugin-mafviewer.umd.production.min.js", |
643 } | 654 } |
644 ] | 655 ] |
645 } | 656 } |
646 categ = trackData['category'] | 657 categ = trackData["category"] |
647 fname = "%s.bed" % tId | 658 fname = "%s.bed" % tId |
648 dest = "%s/%s" % (self.outdir, fname) | 659 dest = "%s/%s" % (self.outdir, fname) |
649 gname = self.genome_name | 660 gname = self.genome_name |
650 cmd = [ | 661 cmd = [ |
651 "bash", | 662 "bash", |
663 ps.wait() | 674 ps.wait() |
664 outp = output.decode("ascii") | 675 outp = output.decode("ascii") |
665 soutp = outp.split("\n") | 676 soutp = outp.split("\n") |
666 samp = [x.split("s ")[1] for x in soutp if x.startswith("s ")] | 677 samp = [x.split("s ")[1] for x in soutp if x.startswith("s ")] |
667 samples = [x.split(".")[0] for x in samp] | 678 samples = [x.split(".")[0] for x in samp] |
679 logging.warn("### maf convert cmd = %s,\nsamples=%s" % (' '.join(cmd), samples)) | |
668 trackDict = { | 680 trackDict = { |
669 "type": "MafTrack", | 681 "type": "MafTrack", |
670 "trackId": tId, | 682 "trackId": tId, |
671 "name": trackData["name"], | 683 "name": trackData["name"], |
672 "category": [categ,], | 684 "category": [ |
685 categ, | |
686 ], | |
673 "adapter": { | 687 "adapter": { |
674 "type": "MafTabixAdapter", | 688 "type": "MafTabixAdapter", |
675 "samples": samples, | 689 "samples": samples, |
676 "bedGzLocation": { | 690 "bedGzLocation": { |
677 "uri": fname + ".sorted.bed.gz", | 691 "uri": fname + ".sorted.bed.gz", |
692 "type": "LinearArcDisplay", | 706 "type": "LinearArcDisplay", |
693 "displayId": "%s-LinearArcDisplay" % tId, | 707 "displayId": "%s-LinearArcDisplay" % tId, |
694 }, | 708 }, |
695 ], | 709 ], |
696 } | 710 } |
697 style_json = self._prepare_track_style(trackDict) | |
698 trackDict["style"] = style_json | |
699 self.tracksToAdd.append(trackDict) | 711 self.tracksToAdd.append(trackDict) |
700 self.trackIdlist.append(tId) | 712 self.trackIdlist.append(tId) |
701 if self.config_json.get("plugins", None): | 713 if self.config_json.get("plugins", None): |
702 self.config_json["plugins"].append(mafPlugin[0]) | 714 self.config_json["plugins"].append(mafPlugin[0]) |
703 else: | 715 else: |
715 str(min_gap), | 727 str(min_gap), |
716 xml, | 728 xml, |
717 ] | 729 ] |
718 subprocess.check_call(cmd, cwd=self.outdir, stdout=gff3_unrebased) | 730 subprocess.check_call(cmd, cwd=self.outdir, stdout=gff3_unrebased) |
719 gff3_unrebased.close() | 731 gff3_unrebased.close() |
732 logging.warn("### blastxml to gff3 cmd = %s" % ' '.join(cmd)) | |
720 return gff3_unrebased.name | 733 return gff3_unrebased.name |
721 | 734 |
722 def add_blastxml(self, data, trackData, blastOpts, **kwargs): | 735 def add_blastxml(self, data, trackData, blastOpts, **kwargs): |
723 gff3 = self._blastxml_to_gff3(data, min_gap=blastOpts["min_gap"]) | 736 gff3 = self._blastxml_to_gff3(data, min_gap=blastOpts["min_gap"]) |
724 | |
725 if "parent" in blastOpts and blastOpts["parent"] != "None": | 737 if "parent" in blastOpts and blastOpts["parent"] != "None": |
726 gff3_rebased = tempfile.NamedTemporaryFile(delete=False) | 738 gff3_rebased = tempfile.NamedTemporaryFile(delete=False) |
727 cmd = ["python", os.path.join(INSTALLED_TO, "gff3_rebase.py")] | 739 cmd = ["python", os.path.join(INSTALLED_TO, "gff3_rebase.py")] |
728 if blastOpts.get("protein", "false") == "true": | 740 if blastOpts.get("protein", "false") == "true": |
729 cmd.append("--protein2dna") | 741 cmd.append("--protein2dna") |
730 cmd.extend([os.path.realpath(blastOpts["parent"]), gff3]) | 742 cmd.extend([os.path.realpath(blastOpts["parent"]), gff3]) |
731 subprocess.check_call(cmd, cwd=self.outdir, stdout=gff3_rebased) | 743 subprocess.check_call(cmd, cwd=self.outdir, stdout=gff3_rebased) |
744 logging.warn("### gff3rebase cmd = %s" % ' '.join(cmd)) | |
732 gff3_rebased.close() | 745 gff3_rebased.close() |
733 | |
734 # Replace original gff3 file | 746 # Replace original gff3 file |
735 shutil.copy(gff3_rebased.name, gff3) | 747 shutil.copy(gff3_rebased.name, gff3) |
736 os.unlink(gff3_rebased.name) | 748 os.unlink(gff3_rebased.name) |
737 url = "%s.gff3" % trackData["label"] | 749 url = "%s.gff3.gz" % trackData["label"] |
738 dest = "%s/%s" % (self.outdir, url) | 750 dest = "%s/%s" % (self.outdir, url) |
739 self._sort_gff(gff3, dest) | 751 self._sort_gff(gff3, dest) |
740 url = url + ".gz" | |
741 tId = trackData["label"] | 752 tId = trackData["label"] |
742 categ = trackData['category'] | 753 categ = trackData["category"] |
743 trackDict = { | 754 trackDict = { |
744 "type": "FeatureTrack", | 755 "type": "FeatureTrack", |
745 "trackId": tId, | 756 "trackId": tId, |
746 "name": trackData["name"], | 757 "name": trackData["name"], |
747 "assemblyNames": [self.genome_name], | 758 "assemblyNames": [self.genome_name], |
748 "category": [categ,], | 759 "category": [ |
760 categ, | |
761 ], | |
749 "adapter": { | 762 "adapter": { |
750 "type": "Gff3TabixAdapter", | 763 "type": "Gff3TabixAdapter", |
751 "gffGzLocation": { | 764 "gffGzLocation": { |
752 "uri": url, | 765 "uri": url, |
753 }, | 766 }, |
766 "type": "LinearArcDisplay", | 779 "type": "LinearArcDisplay", |
767 "displayId": "%s-LinearArcDisplay" % tId, | 780 "displayId": "%s-LinearArcDisplay" % tId, |
768 }, | 781 }, |
769 ], | 782 ], |
770 } | 783 } |
771 style_json = self._prepare_track_style(trackDict) | |
772 trackDict["style"] = style_json | |
773 self.tracksToAdd.append(trackDict) | 784 self.tracksToAdd.append(trackDict) |
774 self.trackIdlist.append(tId) | 785 self.trackIdlist.append(tId) |
775 os.unlink(gff3) | 786 os.unlink(gff3) |
776 | 787 |
777 def add_bigwig(self, data, trackData): | 788 def add_bigwig(self, data, trackData): |
792 dest = os.path.join(self.outdir, url) | 803 dest = os.path.join(self.outdir, url) |
793 cmd = ["cp", data, dest] | 804 cmd = ["cp", data, dest] |
794 self.subprocess_check_call(cmd) | 805 self.subprocess_check_call(cmd) |
795 bwloc = {"uri": url} | 806 bwloc = {"uri": url} |
796 tId = trackData["label"] | 807 tId = trackData["label"] |
797 categ = trackData['category'] | 808 categ = trackData["category"] |
798 trackDict = { | 809 trackDict = { |
799 "type": "QuantitativeTrack", | 810 "type": "QuantitativeTrack", |
800 "trackId": tId, | 811 "trackId": tId, |
801 "name": trackData["name"], | 812 "name": trackData["name"], |
802 "category": [categ,], | 813 "category": [ |
814 categ, | |
815 ], | |
803 "assemblyNames": [ | 816 "assemblyNames": [ |
804 self.genome_name, | 817 self.genome_name, |
805 ], | 818 ], |
806 "adapter": { | 819 "adapter": { |
807 "type": "BigWigAdapter", | 820 "type": "BigWigAdapter", |
812 "type": "LinearWiggleDisplay", | 825 "type": "LinearWiggleDisplay", |
813 "displayId": "%s-LinearWiggleDisplay" % tId, | 826 "displayId": "%s-LinearWiggleDisplay" % tId, |
814 } | 827 } |
815 ], | 828 ], |
816 } | 829 } |
817 style_json = self._prepare_track_style(trackDict) | |
818 trackDict["style"] = style_json | |
819 self.tracksToAdd.append(trackDict) | 830 self.tracksToAdd.append(trackDict) |
820 self.trackIdlist.append(tId) | 831 self.trackIdlist.append(tId) |
821 | 832 |
822 def add_bam(self, data, trackData, bam_index=None, **kwargs): | 833 def add_bam(self, data, trackData, bam_index=None, **kwargs): |
823 tId = trackData["label"] | 834 tId = trackData["label"] |
824 useuri = trackData["useuri"].lower() == "yes" | 835 useuri = trackData["useuri"].lower() == "yes" |
825 bindex = bam_index | 836 bindex = bam_index |
826 categ = trackData['category'] | 837 categ = trackData["category"] |
827 if useuri: | 838 if useuri: |
828 url = data | 839 url = data |
829 else: | 840 else: |
830 fname = "%s.bam" % trackData["label"] | 841 fname = "%s.bam" % trackData["label"] |
831 dest = "%s/%s" % (self.outdir, fname) | 842 dest = "%s/%s" % (self.outdir, fname) |
832 url = fname | 843 url = fname |
833 bindex = fname + '.bai' | 844 bindex = fname + ".bai" |
834 self.subprocess_check_call(["cp", data, dest]) | 845 self.subprocess_check_call(["cp", data, dest]) |
835 if bam_index is not None and os.path.exists(bam_index): | 846 if bam_index is not None and os.path.exists(bam_index): |
836 if not os.path.exists(bindex): | 847 if not os.path.exists(bindex): |
837 # bai most probably made by galaxy and stored in galaxy dirs, need to copy it to dest | 848 # bai most probably made by galaxy and stored in galaxy dirs, need to copy it to dest |
838 self.subprocess_check_call( | 849 self.subprocess_check_call(["cp", bam_index, bindex]) |
839 ["cp", bam_index, bindex] | |
840 ) | |
841 else: | 850 else: |
842 # Can happen in exotic condition | 851 # Can happen in exotic condition |
843 # e.g. if bam imported as symlink with datatype=unsorted.bam, then datatype changed to bam | 852 # e.g. if bam imported as symlink with datatype=unsorted.bam, then datatype changed to bam |
844 # => no index generated by galaxy, but there might be one next to the symlink target | 853 # => no index generated by galaxy, but there might be one next to the symlink target |
845 # this trick allows to skip the bam sorting made by galaxy if already done outside | 854 # this trick allows to skip the bam sorting made by galaxy if already done outside |
849 log.warn("Could not find a bam index (.bai file) for %s", data) | 858 log.warn("Could not find a bam index (.bai file) for %s", data) |
850 trackDict = { | 859 trackDict = { |
851 "type": "AlignmentsTrack", | 860 "type": "AlignmentsTrack", |
852 "trackId": tId, | 861 "trackId": tId, |
853 "name": trackData["name"], | 862 "name": trackData["name"], |
854 "category": [categ,], | 863 "category": [ |
864 categ, | |
865 ], | |
855 "assemblyNames": [self.genome_name], | 866 "assemblyNames": [self.genome_name], |
856 "adapter": { | 867 "adapter": { |
857 "type": "BamAdapter", | 868 "type": "BamAdapter", |
858 "bamLocation": {"uri": url}, | 869 "bamLocation": {"uri": url}, |
859 "index": { | 870 "index": { |
867 "type": "LinearAlignmentsDisplay", | 878 "type": "LinearAlignmentsDisplay", |
868 "displayId": "%s-LinearAlignmentsDisplay" % tId, | 879 "displayId": "%s-LinearAlignmentsDisplay" % tId, |
869 }, | 880 }, |
870 ], | 881 ], |
871 } | 882 } |
872 style_json = self._prepare_track_style(trackDict) | |
873 trackDict["style"] = style_json | |
874 self.tracksToAdd.append(trackDict) | 883 self.tracksToAdd.append(trackDict) |
875 self.trackIdlist.append(tId) | 884 self.trackIdlist.append(tId) |
876 | 885 |
877 def add_cram(self, data, trackData, cram_index=None, **kwargs): | 886 def add_cram(self, data, trackData, cram_index=None, **kwargs): |
878 tId = trackData["label"] | 887 tId = trackData["label"] |
879 categ = trackData['category'] | 888 categ = trackData["category"] |
880 useuri = trackData["useuri"].lower() == "yes" | 889 useuri = trackData["useuri"].lower() == "yes" |
881 if useuri: | 890 if useuri: |
882 url = data | 891 url = data |
883 else: | 892 else: |
884 fname = "%s.cram" % trackData["label"] | 893 fname = "%s.cram" % trackData["label"] |
885 dest = "%s/%s" % (self.outdir, fname) | 894 dest = "%s/%s" % (self.outdir, fname) |
886 url = fname | 895 url = fname |
887 self.subprocess_check_call(["cp", data, dest]) | 896 self.subprocess_check_call(["cp", data, dest]) |
888 if cram_index is not None and os.path.exists(cram_index): | 897 if cram_index is not None and os.path.exists(cram_index): |
889 if not os.path.exists(dest+'.crai'): | 898 if not os.path.exists(dest + ".crai"): |
890 # most probably made by galaxy and stored in galaxy dirs, need to copy it to dest | 899 # most probably made by galaxy and stored in galaxy dirs, need to copy it to dest |
891 self.subprocess_check_call( | 900 self.subprocess_check_call( |
892 ["cp", os.path.realpath(cram_index), dest + ".crai"] | 901 ["cp", os.path.realpath(cram_index), dest + ".crai"] |
893 ) | 902 ) |
894 else: | 903 else: |
895 cpath = os.path.realpath(dest) + '.crai' | 904 cpath = os.path.realpath(dest) + ".crai" |
896 cmd = ["samtools", "index", "-c", "-o", cpath, os.path.realpath(dest)] | 905 cmd = ["samtools", "index", "-c", "-o", cpath, os.path.realpath(dest)] |
897 logging.debug('executing cmd %s' % ' '.join(cmd)) | 906 logging.debug("executing cmd %s" % " ".join(cmd)) |
898 self.subprocess_check_call(cmd) | 907 self.subprocess_check_call(cmd) |
899 trackDict = { | 908 trackDict = { |
900 "type": "AlignmentsTrack", | 909 "type": "AlignmentsTrack", |
901 "trackId": tId, | 910 "trackId": tId, |
902 "name": trackData["name"], | 911 "name": trackData["name"], |
903 "category": [categ,], | 912 "category": [ |
913 categ, | |
914 ], | |
904 "assemblyNames": [self.genome_name], | 915 "assemblyNames": [self.genome_name], |
905 "adapter": { | 916 "adapter": { |
906 "type": "CramAdapter", | 917 "type": "CramAdapter", |
907 "cramLocation": {"uri": url}, | 918 "cramLocation": {"uri": url}, |
908 "craiLocation": { | 919 "craiLocation": { |
909 "uri": url + '.crai', | 920 "uri": url + ".crai", |
910 }, | 921 }, |
911 "sequenceAdapter": self.genome_sequence_adapter, | 922 "sequenceAdapter": self.genome_sequence_adapter, |
912 }, | 923 }, |
913 "displays": [ | 924 "displays": [ |
914 { | 925 { |
915 "type": "LinearAlignmentsDisplay", | 926 "type": "LinearAlignmentsDisplay", |
916 "displayId": "%s-LinearAlignmentsDisplay" % tId, | 927 "displayId": "%s-LinearAlignmentsDisplay" % tId, |
917 }, | 928 }, |
918 ], | 929 ], |
919 } | 930 } |
920 style_json = self._prepare_track_style(trackDict) | |
921 trackDict["style"] = style_json | |
922 self.tracksToAdd.append(trackDict) | 931 self.tracksToAdd.append(trackDict) |
923 self.trackIdlist.append(tId) | 932 self.trackIdlist.append(tId) |
924 | 933 |
925 def add_vcf(self, data, trackData): | 934 def add_vcf(self, data, trackData): |
926 tId = trackData["label"] | 935 tId = trackData["label"] |
927 # url = "%s/api/datasets/%s/display" % ( | 936 # url = "%s/api/datasets/%s/display" % ( |
928 # self.giURL, | 937 # self.giURL, |
929 # trackData["metadata"]["dataset_id"], | 938 # trackData["metadata"]["dataset_id"], |
930 # ) | 939 # ) |
931 categ = trackData['category'] | 940 categ = trackData["category"] |
932 useuri = trackData["useuri"].lower() == "yes" | 941 useuri = trackData["useuri"].lower() == "yes" |
933 if useuri: | 942 if useuri: |
934 url = data | 943 url = data |
935 else: | 944 else: |
936 url = "%s.vcf.gz" % tId | 945 url = "%s.vcf.gz" % tId |
942 trackDict = { | 951 trackDict = { |
943 "type": "VariantTrack", | 952 "type": "VariantTrack", |
944 "trackId": tId, | 953 "trackId": tId, |
945 "name": trackData["name"], | 954 "name": trackData["name"], |
946 "assemblyNames": [self.genome_name], | 955 "assemblyNames": [self.genome_name], |
947 "category": [categ,], | 956 "category": [ |
957 categ, | |
958 ], | |
948 "adapter": { | 959 "adapter": { |
949 "type": "VcfTabixAdapter", | 960 "type": "VcfTabixAdapter", |
950 "vcfGzLocation": { | 961 "vcfGzLocation": {"uri": url}, |
951 "uri": url | |
952 }, | |
953 "index": { | 962 "index": { |
954 "location": { | 963 "location": { |
955 "uri": url + ".tbi", | 964 "uri": url + ".tbi", |
956 } | 965 } |
957 }, | 966 }, |
969 "type": "LinearPairedArcDisplay", | 978 "type": "LinearPairedArcDisplay", |
970 "displayId": "%s-LinearPairedArcDisplay" % tId, | 979 "displayId": "%s-LinearPairedArcDisplay" % tId, |
971 }, | 980 }, |
972 ], | 981 ], |
973 } | 982 } |
974 style_json = self._prepare_track_style(trackDict) | |
975 trackDict["style"] = style_json | |
976 self.tracksToAdd.append(trackDict) | 983 self.tracksToAdd.append(trackDict) |
977 self.trackIdlist.append(tId) | 984 self.trackIdlist.append(tId) |
978 | 985 |
979 def _sort_gff(self, data, dest): | 986 def _sort_gff(self, data, dest): |
980 # Only index if not already done | 987 # Only index if not already done |
1001 else: | 1008 else: |
1002 url = "%s.%s.gz" % (trackData["label"], ext) | 1009 url = "%s.%s.gz" % (trackData["label"], ext) |
1003 dest = "%s/%s" % (self.outdir, url) | 1010 dest = "%s/%s" % (self.outdir, url) |
1004 self._sort_gff(data, dest) | 1011 self._sort_gff(data, dest) |
1005 tId = trackData["label"] | 1012 tId = trackData["label"] |
1006 categ = trackData['category'] | 1013 categ = trackData["category"] |
1007 trackDict = { | 1014 trackDict = { |
1008 "type": "FeatureTrack", | 1015 "type": "FeatureTrack", |
1009 "trackId": tId, | 1016 "trackId": tId, |
1010 "name": trackData["name"], | 1017 "name": trackData["name"], |
1011 "assemblyNames": [self.genome_name], | 1018 "assemblyNames": [self.genome_name], |
1012 "category": [categ,], | 1019 "category": [ |
1020 categ, | |
1021 ], | |
1013 "adapter": { | 1022 "adapter": { |
1014 "type": "Gff3TabixAdapter", | 1023 "type": "Gff3TabixAdapter", |
1015 "gffGzLocation": { | 1024 "gffGzLocation": { |
1016 "uri": url, | 1025 "uri": url, |
1017 }, | 1026 }, |
1030 "type": "LinearArcDisplay", | 1039 "type": "LinearArcDisplay", |
1031 "displayId": "%s-LinearArcDisplay" % tId, | 1040 "displayId": "%s-LinearArcDisplay" % tId, |
1032 }, | 1041 }, |
1033 ], | 1042 ], |
1034 } | 1043 } |
1035 style_json = self._prepare_track_style(trackDict) | |
1036 trackDict["style"] = style_json | |
1037 self.tracksToAdd.append(trackDict) | 1044 self.tracksToAdd.append(trackDict) |
1038 self.trackIdlist.append(tId) | 1045 self.trackIdlist.append(tId) |
1039 | 1046 |
1040 def add_bed(self, data, ext, trackData): | 1047 def add_bed(self, data, ext, trackData): |
1041 tId = trackData["label"] | 1048 tId = trackData["label"] |
1042 categ = trackData['category'] | 1049 categ = trackData["category"] |
1043 useuri = trackData["useuri"].lower() == "yes" | 1050 useuri = trackData["useuri"].lower() == "yes" |
1044 if useuri: | 1051 if useuri: |
1045 url = data | 1052 url = data |
1046 else: | 1053 else: |
1047 url = "%s.%s.gz" % (trackData["label"], ext) | 1054 url = "%s.%s.gz" % (trackData["label"], ext) |
1051 "type": "FeatureTrack", | 1058 "type": "FeatureTrack", |
1052 "trackId": tId, | 1059 "trackId": tId, |
1053 "name": trackData["name"], | 1060 "name": trackData["name"], |
1054 "assemblyNames": [self.genome_name], | 1061 "assemblyNames": [self.genome_name], |
1055 "adapter": { | 1062 "adapter": { |
1056 "category": [categ,], | 1063 "category": [ |
1064 categ, | |
1065 ], | |
1057 "type": "BedTabixAdapter", | 1066 "type": "BedTabixAdapter", |
1058 "bedGzLocation": { | 1067 "bedGzLocation": { |
1059 "uri": url, | 1068 "uri": url, |
1060 }, | 1069 }, |
1061 "index": { | 1070 "index": { |
1077 "type": "LinearArcDisplay", | 1086 "type": "LinearArcDisplay", |
1078 "displayId": "%s-LinearArcDisplay" % tId, | 1087 "displayId": "%s-LinearArcDisplay" % tId, |
1079 }, | 1088 }, |
1080 ], | 1089 ], |
1081 } | 1090 } |
1082 style_json = self._prepare_track_style(trackDict) | |
1083 trackDict["style"] = style_json | |
1084 self.tracksToAdd.append(trackDict) | 1091 self.tracksToAdd.append(trackDict) |
1085 self.trackIdlist.append(tId) | 1092 self.trackIdlist.append(tId) |
1086 | 1093 |
1087 def add_paf(self, data, trackData, pafOpts, **kwargs): | 1094 def add_paf(self, data, trackData, pafOpts, **kwargs): |
1088 tname = trackData["name"] | 1095 tname = trackData["name"] |
1089 tId = trackData["label"] | 1096 tId = trackData["label"] |
1090 categ = trackData['category'] | 1097 categ = trackData["category"] |
1091 pgnames = [x.strip() for x in pafOpts["genome_label"].split(",")] | 1098 pgnames = [x.strip() for x in pafOpts["genome_label"].split(",")] |
1092 pgpaths = [x.strip() for x in pafOpts["genome"].split(",")] | 1099 pgpaths = [x.strip() for x in pafOpts["genome"].split(",")] |
1093 passnames = [self.genome_name] # always first | 1100 passnames = [self.genome_name] # always first |
1094 for i, gname in enumerate(pgnames): | 1101 for i, gname in enumerate(pgnames): |
1095 if len(gname.split()) > 1: | 1102 if len(gname.split()) > 1: |
1096 gname = gname.split()[0] | 1103 gname = gname.split()[0] |
1097 passnames.append(gname) | 1104 passnames.append(gname) |
1098 # trouble from spacey names in command lines avoidance | 1105 # trouble from spacey names in command lines avoidance |
1099 if gname not in self.genome_names: | 1106 if gname not in self.genome_names: |
1100 # ignore if already there - eg for duplicates among pafs. | 1107 # ignore if already there - eg for duplicates among pafs. |
1101 useuri = pgpaths[i].startswith('http://') or pgpaths[i].startswith('https://') | 1108 useuri = pgpaths[i].startswith("http://") or pgpaths[i].startswith( |
1109 "https://" | |
1110 ) | |
1102 asstrack = self.make_assembly(pgpaths[i], gname, useuri) | 1111 asstrack = self.make_assembly(pgpaths[i], gname, useuri) |
1103 self.genome_names.append(gname) | 1112 self.genome_names.append(gname) |
1104 if self.config_json.get("assemblies", None): | 1113 if self.config_json.get("assemblies", None): |
1105 self.config_json["assemblies"].append(asstrack) | 1114 self.config_json["assemblies"].append(asstrack) |
1106 else: | 1115 else: |
1112 self.symlink_or_copy(os.path.realpath(data), dest) | 1121 self.symlink_or_copy(os.path.realpath(data), dest) |
1113 trackDict = { | 1122 trackDict = { |
1114 "type": "SyntenyTrack", | 1123 "type": "SyntenyTrack", |
1115 "trackId": tId, | 1124 "trackId": tId, |
1116 "assemblyNames": passnames, | 1125 "assemblyNames": passnames, |
1117 "category": [categ,], | 1126 "category": [ |
1127 categ, | |
1128 ], | |
1118 "name": tname, | 1129 "name": tname, |
1119 "adapter": { | 1130 "adapter": { |
1120 "type": "PAFAdapter", | 1131 "type": "PAFAdapter", |
1121 "pafLocation": {"uri": url}, | 1132 "pafLocation": {"uri": url}, |
1122 "assemblyNames": passnames, | 1133 "assemblyNames": passnames, |
1123 }, | 1134 }, |
1124 "displays": [ | 1135 "displays": [ |
1125 { | 1136 { |
1126 "type": "LinearSyntenyDisplay", | 1137 "type": "LinearSyntenyDisplay", |
1127 "displayId": "%s-LinearSyntenyDisplay" % tId, | 1138 "displayId": "%s-LinearSyntenyDisplay" % tId, |
1128 }, | 1139 }, |
1129 { | 1140 { |
1130 "type": "DotPlotDisplay", | 1141 "type": "DotPlotDisplay", |
1131 "displayId": "%s-DotPlotDisplay" % tId, | 1142 "displayId": "%s-DotPlotDisplay" % tId, |
1132 }, | 1143 }, |
1133 ], | 1144 ], |
1134 } | 1145 } |
1135 style_json = self._prepare_track_style(trackDict) | |
1136 trackDict["style"] = style_json | |
1137 self.tracksToAdd.append(trackDict) | 1146 self.tracksToAdd.append(trackDict) |
1138 self.trackIdlist.append(tId) | 1147 self.trackIdlist.append(tId) |
1139 | 1148 |
1140 def process_annotations(self, track): | 1149 def process_annotations(self, track): |
1141 category = track["category"].replace("__pd__date__pd__", TODAY) | 1150 category = track["category"].replace("__pd__date__pd__", TODAY) |
1247 else: | 1256 else: |
1248 logging.warn("Do not know how to handle %s", dataset_ext) | 1257 logging.warn("Do not know how to handle %s", dataset_ext) |
1249 # Return non-human label for use in other fields | 1258 # Return non-human label for use in other fields |
1250 yield outputTrackConfig["label"] | 1259 yield outputTrackConfig["label"] |
1251 | 1260 |
1252 def add_default_session(self, data): | 1261 def add_default_session(self, default_data): |
1253 """ | 1262 """ |
1254 Add some default session settings: set some assemblies/tracks on/off | 1263 Add some default session settings: set some assemblies/tracks on/off |
1255 """ | 1264 """ |
1256 tracks_data = [] | 1265 tracks_data = [] |
1257 | 1266 |
1265 config_json.update(self.config_json) | 1274 config_json.update(self.config_json) |
1266 | 1275 |
1267 for track_conf in self.tracksToAdd: | 1276 for track_conf in self.tracksToAdd: |
1268 track_types[track_conf["trackId"]] = track_conf["type"] | 1277 track_types[track_conf["trackId"]] = track_conf["type"] |
1269 tId = track_conf["trackId"] | 1278 tId = track_conf["trackId"] |
1270 if tId in data["visibility"]["default_on"]: | 1279 #if tId in data["visibility"]["default_on"]: |
1280 style_data = default_data["style"].get(tId, None) | |
1281 if not style_data: | |
1282 logging.warn("### No style data in default data for %s" % tId) | |
1271 style_data = {"type": "LinearBasicDisplay"} | 1283 style_data = {"type": "LinearBasicDisplay"} |
1272 if "displays" in track_conf: | 1284 if "displays" in track_conf: |
1273 style_data["type"] = track_conf["displays"][0]["type"] | 1285 disp = track_conf["displays"][0]["type"] |
1274 if track_conf.get("style_labels", None): | 1286 style_data["type"] = disp |
1275 # TODO fix this: it should probably go in a renderer block (SvgFeatureRenderer) but still does not work | 1287 style_data["configuration"] = "%s-%s" % (tId, disp) |
1276 # TODO move this to per track displays? | 1288 if track_conf.get("style_labels", None): |
1277 style_data["labels"] = track_conf["style_labels"] | 1289 # TODO fix this: it should probably go in a renderer block (SvgFeatureRenderer) but still does not work |
1278 tracks_data.append( | 1290 # TODO move this to per track displays? |
1279 { | 1291 style_data["labels"] = track_conf["style_labels"] |
1280 "type": track_types[tId], | 1292 tracks_data.append( |
1281 "configuration": tId, | 1293 { |
1282 "displays": [style_data], | 1294 "type": track_types[tId], |
1283 } | 1295 "configuration": tId, |
1284 ) | 1296 "displays": [style_data], |
1297 } | |
1298 ) | |
1285 | 1299 |
1286 # The view for the assembly we're adding | 1300 # The view for the assembly we're adding |
1287 view_json = {"type": "LinearGenomeView", "tracks": tracks_data} | 1301 view_json = {"type": "LinearGenomeView", "tracks": tracks_data} |
1288 | 1302 |
1289 refName = None | 1303 refName = None |
1290 drdict = { | 1304 drdict = { |
1291 "reversed": False, | 1305 "reversed": False, |
1292 "assemblyName": self.genome_name, | 1306 "assemblyName": self.genome_name, |
1293 "start": 2000, | 1307 "start": 1, |
1294 "end": 200000, | 1308 "end": 100000, |
1295 "refName": "x", | 1309 "refName": "x", |
1296 } | 1310 } |
1297 | 1311 |
1298 if data.get("defaultLocation", ""): | 1312 if default_data.get("defaultLocation", ""): |
1299 ddl = data["defaultLocation"] | 1313 ddl = default_data["defaultLocation"] |
1300 loc_match = re.search(r"^([^:]+):([\d,]*)\.*([\d,]*)$", ddl) | 1314 loc_match = re.search(r"^([^:]+):([\d,]*)\.*([\d,]*)$", ddl) |
1301 # allow commas like 100,000 but ignore as integer | 1315 # allow commas like 100,000 but ignore as integer |
1302 if loc_match: | 1316 if loc_match: |
1303 refName = loc_match.group(1) | 1317 refName = loc_match.group(1) |
1304 drdict["refName"] = refName | 1318 drdict["refName"] = refName |
1322 logging.info("@@@ defaultlocation %s for default session" % drdict) | 1336 logging.info("@@@ defaultlocation %s for default session" % drdict) |
1323 else: | 1337 else: |
1324 logging.info( | 1338 logging.info( |
1325 "@@@ no contig name found for default session - please add one!" | 1339 "@@@ no contig name found for default session - please add one!" |
1326 ) | 1340 ) |
1327 session_name = data.get("session_name", "New session") | 1341 session_name = default_data.get("session_name", "New session") |
1328 for key, value in mapped_chars.items(): | 1342 for key, value in mapped_chars.items(): |
1329 session_name = session_name.replace(value, key) | 1343 session_name = session_name.replace(value, key) |
1330 # Merge with possibly existing defaultSession (if upgrading a jbrowse instance) | 1344 # Merge with possibly existing defaultSession (if upgrading a jbrowse instance) |
1331 session_json = {} | 1345 session_json = {} |
1332 if "defaultSession" in config_json: | 1346 if "defaultSession" in config_json: |
1380 | 1394 |
1381 def clone_jbrowse(self, realclone=True): | 1395 def clone_jbrowse(self, realclone=True): |
1382 """Clone a JBrowse directory into a destination directory. This also works in Biocontainer testing now""" | 1396 """Clone a JBrowse directory into a destination directory. This also works in Biocontainer testing now""" |
1383 dest = self.outdir | 1397 dest = self.outdir |
1384 if realclone: | 1398 if realclone: |
1385 self.subprocess_check_call(['jbrowse', 'create', dest,"-f", '--tag', f"{JB2VER}"]) | 1399 self.subprocess_check_call( |
1400 ["jbrowse", "create", dest, "-f", "--tag", f"{JB2VER}"] | |
1401 ) | |
1386 else: | 1402 else: |
1387 shutil.copytree(self.jbrowse2path, dest, dirs_exist_ok=True) | 1403 shutil.copytree(self.jbrowse2path, dest, dirs_exist_ok=True) |
1388 for fn in [ | 1404 for fn in [ |
1389 "asset-manifest.json", | 1405 "asset-manifest.json", |
1390 "favicon.ico", | 1406 "favicon.ico", |
1398 cmd = ["cp", os.path.join(INSTALLED_TO, "jb2_webserver.py"), dest] | 1414 cmd = ["cp", os.path.join(INSTALLED_TO, "jb2_webserver.py"), dest] |
1399 self.subprocess_check_call(cmd) | 1415 self.subprocess_check_call(cmd) |
1400 | 1416 |
1401 | 1417 |
1402 def parse_style_conf(item): | 1418 def parse_style_conf(item): |
1403 if "type" in item.attrib and item.attrib["type"] in [ | 1419 if item.text.lower() in ['false','true','yes','no']: |
1404 "boolean", | 1420 return item.text.lower in ("yes", "true") |
1405 "integer", | |
1406 ]: | |
1407 if item.attrib["type"] == "boolean": | |
1408 return item.text in ("yes", "true", "True") | |
1409 elif item.attrib["type"] == "integer": | |
1410 return int(item.text) | |
1411 else: | 1421 else: |
1412 return item.text | 1422 return item.text |
1413 | 1423 |
1414 | 1424 |
1415 if __name__ == "__main__": | 1425 if __name__ == "__main__": |
1471 pass | 1481 pass |
1472 | 1482 |
1473 trackfiles = track.findall("files/trackFile") | 1483 trackfiles = track.findall("files/trackFile") |
1474 if trackfiles: | 1484 if trackfiles: |
1475 for x in track.findall("files/trackFile"): | 1485 for x in track.findall("files/trackFile"): |
1486 track_conf["label"] = x.attrib["label"] | |
1476 track_conf["useuri"] = x.attrib["useuri"] | 1487 track_conf["useuri"] = x.attrib["useuri"] |
1477 if is_multi_bigwig: | 1488 if is_multi_bigwig: |
1478 multi_bigwig_paths.append( | 1489 multi_bigwig_paths.append( |
1479 ( | 1490 ( |
1480 x.attrib["label"], | 1491 x.attrib["label"], |
1519 track_conf["format"] = track.attrib["format"] | 1530 track_conf["format"] = track.attrib["format"] |
1520 if track.find("options/style"): | 1531 if track.find("options/style"): |
1521 track_conf["style"] = { | 1532 track_conf["style"] = { |
1522 item.tag: parse_style_conf(item) for item in track.find("options/style") | 1533 item.tag: parse_style_conf(item) for item in track.find("options/style") |
1523 } | 1534 } |
1535 else: | |
1536 track_conf["style"] = {} | |
1537 tst = track_conf["style"].get("type", None) | |
1538 if tst: | |
1539 track_conf["style"]["configuration"] = "%s-%s" % (track_conf["label"], tst) | |
1524 if track.find("options/style_labels"): | 1540 if track.find("options/style_labels"): |
1525 track_conf["style_labels"] = { | 1541 track_conf["style_labels"] = { |
1526 item.tag: parse_style_conf(item) | 1542 item.tag: parse_style_conf(item) |
1527 for item in track.find("options/style_labels") | 1543 for item in track.find("options/style_labels") |
1528 } | 1544 } |
1529 | 1545 |
1530 track_conf["conf"] = etree_to_dict(track.find("options")) | 1546 track_conf["conf"] = etree_to_dict(track.find("options")) |
1531 track_conf["category"] = track.attrib["cat"] | 1547 track_conf["category"] = track.attrib["cat"] |
1532 track_conf["format"] = track.attrib["format"] | 1548 track_conf["format"] = track.attrib["format"] |
1533 try: | |
1534 # Only pertains to gff3 + blastxml. TODO? | |
1535 track_conf["style"] = {t.tag: t.text for t in track.find("options/style")} | |
1536 except TypeError: | |
1537 track_conf["style"] = {} | |
1538 pass | |
1539 keys = jc.process_annotations(track_conf) | 1549 keys = jc.process_annotations(track_conf) |
1540 | 1550 |
1541 if keys: | 1551 if keys: |
1542 for key in keys: | 1552 for key in keys: |
1543 default_session_data["visibility"][ | 1553 default_session_data["visibility"][ |
1544 track.attrib.get("visibility", "default_off") | 1554 track.attrib.get("visibility", "default_off") |
1545 ].append(key) | 1555 ].append(key) |
1546 if track_conf.get("style", None): | 1556 if track_conf.get("style", None): |
1547 default_session_data["style"][key] = track_conf[ | 1557 default_session_data["style"][key] = track_conf["style"] |
1548 "style" | |
1549 ] # TODO do we need this anymore? | |
1550 if track_conf.get("style_lables", None): | 1558 if track_conf.get("style_lables", None): |
1551 default_session_data["style_labels"][key] = track_conf.get( | 1559 default_session_data["style_labels"][key] = track_conf.get( |
1552 "style_labels", None | 1560 "style_labels", None |
1553 ) | 1561 ) |
1554 default_session_data["defaultLocation"] = root.find( | 1562 default_session_data["defaultLocation"] = root.find( |