diff jbrowse.py @ 8:ad4b9d7eae6a draft

planemo upload for repository https://github.com/galaxyproject/tools-iuc/tree/master/tools/jbrowse commit 9a243c616a4a3156347e38fdb5f35863ae5133f9
author iuc
date Tue, 29 Nov 2016 10:55:30 -0500
parents ae9382cfb6ac
children 1a6d882d340d
line wrap: on
line diff
--- a/jbrowse.py	Sun Jun 26 10:50:15 2016 -0400
+++ b/jbrowse.py	Tue Nov 29 10:55:30 2016 -0500
@@ -1,17 +1,19 @@
 #!/usr/bin/env python
-import os
+import argparse
 import copy
-import argparse
-import subprocess
 import hashlib
+import json
+import logging
+import os
+import shutil
 import struct
+import subprocess
 import tempfile
-import shutil
-import json
+import xml.etree.ElementTree as ET
+from collections import defaultdict
+
 from Bio.Data import CodonTable
-import xml.etree.ElementTree as ET
-import logging
-from collections import defaultdict
+
 logging.basicConfig(level=logging.INFO)
 log = logging.getLogger('jbrowse')
 
@@ -79,11 +81,11 @@
         """,
         'blast': """
             var opacity = 0;
-            if(score == 0.0) {{
+            if(score == 0.0) {
                 opacity = 1;
-            }} else {{
+            } else{
                 opacity = (20 - Math.log10(score)) / 180;
-            }}
+            }
         """
     }
 
@@ -125,7 +127,7 @@
 
     def rgb_from_hex(self, hexstr):
         # http://stackoverflow.com/questions/4296249/how-do-i-convert-a-hex-triplet-to-an-rgb-tuple-and-back
-        return struct.unpack('BBB',hexstr.decode('hex'))
+        return struct.unpack('BBB', hexstr.decode('hex'))
 
     def min_max_gff(self, gff_file):
         min_val = None
@@ -154,6 +156,31 @@
         self.brewer_colour_idx += 1
         return r, g, b
 
+    def parse_menus(self, track):
+        trackConfig = {'menuTemplate': [{}, {}, {}]}
+
+        if 'menu' in track['menus']:
+            menu_list = [track['menus']['menu']]
+            if isinstance(track['menus']['menu'], list):
+                menu_list = track['menus']['menu']
+
+            for m in menu_list:
+                tpl = {
+                    'action': m['action'],
+                    'label': m.get('label', '{name}'),
+                    'iconClass': m.get('iconClass', 'dijitIconBookmark'),
+                }
+                if 'url' in m:
+                    tpl['url'] = m['url']
+                if 'content' in m:
+                    tpl['content'] = m['content']
+                if 'title' in m:
+                    tpl['title'] = m['title']
+
+                trackConfig['menuTemplate'].append(tpl)
+
+        return trackConfig
+
     def parse_colours(self, track, trackFormat, gff3=None):
         # Wiggle tracks have a bicolor pallete
         trackConfig = {'style': {}}
@@ -166,7 +193,6 @@
                 trackConfig['style']['neg_color'] = self.hex_from_rgb(*self._get_colours())
                 trackConfig['style']['pos_color'] = self.hex_from_rgb(*self._get_colours())
 
-
             # Wiggle tracks can change colour at a specified place
             bc_pivot = track['wiggle']['bicolor_pivot']
             if bc_pivot not in ('mean', 'zero'):
@@ -223,7 +249,7 @@
                         auto_color = "'%s'" % self.hex_from_rgb(*self._get_colours())
 
                     color_function = self.COLOR_FUNCTION_TEMPLATE_QUAL.format(**{
-                        'opacity': self.OPACITY_MATH[algo].format(**{'max': max_val,'min': min_val}),
+                        'opacity': self.OPACITY_MATH[algo].format(**{'max': max_val, 'min': min_val}),
                         'user_spec_color': user_color,
                         'auto_gen_color': auto_color,
                     })
@@ -240,14 +266,14 @@
         for dc in map(etree_to_dict, children):
             for k, v in dc.iteritems():
                 dd[k].append(v)
-        d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}
+        d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}
     if t.attrib:
         d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems())
     if t.text:
         text = t.text.strip()
         if children or t.attrib:
             if text:
-              d[t.tag]['#text'] = text
+                d[t.tag]['#text'] = text
         else:
             d[t.tag] = text
     return d
@@ -274,6 +300,7 @@
         self.genome_paths = genomes
         self.standalone = standalone
         self.gencode = gencode
+        self.tracksToIndex = []
 
         if standalone:
             self.clone_jbrowse(self.jbrowse, self.outdir)
@@ -302,7 +329,6 @@
         with open(trackList, 'w') as handle:
             json.dump(trackListData, handle, indent=2)
 
-
     def subprocess_check_call(self, command):
         log.debug('cd %s && %s', self.outdir, ' '.join(command))
         subprocess.check_call(command, cwd=self.outdir)
@@ -316,11 +342,23 @@
                 'perl', self._jbrowse_bin('prepare-refseqs.pl'),
                 '--fasta', genome_path])
 
-        # Generate name
-        # self.subprocess_check_call([
-            # 'perl', self._jbrowse_bin('generate-names.pl'),
-            # '--hashBits', '16'
-        # ])
+    def generate_names(self):
+        # Generate names
+
+        args = [
+            'perl', self._jbrowse_bin('generate-names.pl'),
+            '--hashBits', '16'
+        ]
+
+        tracks = ','.join(self.tracksToIndex)
+
+        if tracks:
+            args += ['--tracks', tracks]
+        else:
+            # No tracks to index, index only the refseq
+            args += ['--tracks', 'DNA']
+
+        self.subprocess_check_call(args)
 
     def _add_json(self, json_data):
 
@@ -343,7 +381,6 @@
         self.subprocess_check_call(cmd)
         os.unlink(tmp.name)
 
-
     def _blastxml_to_gff3(self, xml, min_gap=10):
         gff3_unrebased = tempfile.NamedTemporaryFile(delete=False)
         cmd = ['python', os.path.join(INSTALLED_TO, 'blastxml_to_gapped_gff3.py'),
@@ -389,6 +426,9 @@
         self.subprocess_check_call(cmd)
         os.unlink(gff3)
 
+        if blastOpts.get('index', 'false') == 'true':
+            self.tracksToIndex.append("%s" % trackData['label'])
+
     def add_bigwig(self, data, trackData, wiggleOpts, **kwargs):
         dest = os.path.join('data', 'raw', trackData['label'] + '.bw')
         cmd = ['ln', data, dest]
@@ -425,7 +465,6 @@
             "storeClass": "JBrowse/Store/SeqFeature/BAM",
         })
 
-
         self._add_track_json(trackData)
 
         if bamOpts.get('auto_snp', 'false') == 'true':
@@ -433,7 +472,7 @@
             trackData2.update({
                 "type": "JBrowse/View/Track/SNPCoverage",
                 "key": trackData['key'] + " - SNPs/Coverage",
-                "label": trackData['label']  + "_autosnp",
+                "label": trackData['label'] + "_autosnp",
             })
             self._add_track_json(trackData2)
 
@@ -468,7 +507,7 @@
         clientConfig = trackData['style']
         del config['style']
 
-        if  'match' in gffOpts:
+        if 'match' in gffOpts:
             config['glyph'] = 'JBrowse/View/FeatureGlyph/Segments'
             cmd += ['--type', gffOpts['match']]
 
@@ -488,12 +527,14 @@
 
         self.subprocess_check_call(cmd)
 
+        if gffOpts.get('index', 'false') == 'true':
+            self.tracksToIndex.append("%s" % trackData['label'])
 
     def process_annotations(self, track):
         outputTrackConfig = {
             'style': {
-                'label':       track['style'].get('label', 'description'),
-                'className':   track['style'].get('className', 'feature'),
+                'label': track['style'].get('label', 'description'),
+                'className': track['style'].get('className', 'feature'),
                 'description': track['style'].get('description', ''),
             },
             'category': track['category'],
@@ -516,11 +557,14 @@
                 else:
                     outputTrackConfig[key] = colourOptions[key]
 
+            menus = self.cs.parse_menus(track['conf']['options'])
+            outputTrackConfig.update(menus)
+
             # import pprint; pprint.pprint(track)
             # import sys; sys.exit()
             if dataset_ext in ('gff', 'gff3', 'bed'):
                 self.add_features(dataset_path, dataset_ext, outputTrackConfig,
-                                track['conf']['options']['gff'])
+                                  track['conf']['options']['gff'])
             elif dataset_ext == 'bigwig':
                 self.add_bigwig(dataset_path, outputTrackConfig,
                                 track['conf']['options']['wiggle'])
@@ -645,14 +689,14 @@
         try:
             # Only pertains to gff3 + blastxml. TODO?
             track_conf['style'] = {t.tag: t.text for t in track.find('options/style')}
-        except TypeError, te:
+        except TypeError:
             track_conf['style'] = {}
             pass
         track_conf['conf'] = etree_to_dict(track.find('options'))
         keys = jc.process_annotations(track_conf)
 
-
         for key in keys:
             extra_data['visibility'][track.attrib.get('visibility', 'default_off')].append(key)
 
     jc.add_final_data(extra_data)
+    jc.generate_names()