Mercurial > repos > yating-l > jbrowsearchivecreator
comparison TrackHub.py @ 6:237707a6b74d draft
planemo upload for repository https://github.com/Yating-L/jbrowse-archive-creator.git commit a500f7ab2119cc5faaf80393bd87428389d06880-dirty
| author | yating-l |
|---|---|
| date | Thu, 15 Feb 2018 17:05:05 -0500 |
| parents | 7e471cdd9e71 |
| children | 5d5fdcb798da |
comparison
equal
deleted
inserted
replaced
| 5:e762f4b9e4bd | 6:237707a6b74d |
|---|---|
| 3 import os | 3 import os |
| 4 import subprocess | 4 import subprocess |
| 5 import shutil | 5 import shutil |
| 6 import zipfile | 6 import zipfile |
| 7 import json | 7 import json |
| 8 import utils | 8 import tempfile |
| 9 import logging | |
| 10 from mako.lookup import TemplateLookup | |
| 11 | |
| 12 from datatypes.Datatype import Datatype | |
| 13 from tracks.TrackStyles import TrackStyles | |
| 14 from util import subtools | |
| 15 from util import santitizer | |
| 9 | 16 |
| 10 | 17 |
| 11 class TrackHub: | 18 class TrackHub: |
| 12 def __init__(self, inputFiles, reference, outputDirect, tool_dir, genome, extra_files_path, metaData, jbrowse_host): | 19 def __init__(self, inputFastaFile, outputFile, extra_files_path, tool_directory, trackType): |
| 13 self.input_files = inputFiles.tracks | 20 |
| 14 self.outfile = outputDirect | 21 self.rootAssemblyHub = None |
| 15 self.outfolder = extra_files_path | 22 |
| 16 self.out_path = os.path.join(extra_files_path, 'myHub') | 23 self.mySpecieFolderPath = None |
| 17 self.reference = reference | 24 |
| 18 self.tool_dir = tool_dir | 25 # Store intermediate files, will be removed if not in debug mode |
| 19 self.metaData = metaData | 26 self.myTracksFolderPath = None |
| 20 self.raw = os.path.join(self.out_path, 'raw') | 27 |
| 21 self.json = os.path.join(self.out_path, 'json') | 28 # Store binary files: Bam, BigWig |
| 22 self.jbrowse_host = jbrowse_host | 29 self.myBinaryFolderPath = None |
| 23 try: | 30 |
| 24 if os.path.exists(self.json): | 31 self.tool_directory = tool_directory |
| 25 shutil.rmtree(self.json) | 32 self.trackType = trackType |
| 26 os.makedirs(self.json) | 33 self.reference_genome = inputFastaFile |
| 27 except OSError as e: | 34 self.genome_name = inputFastaFile.assembly_id |
| 28 print "Cannot create json folder error({0}): {1}".format(e.errno, e.strerror) | 35 self.extra_files_path = extra_files_path |
| 29 else: | 36 self.outputFile = outputFile |
| 30 print "Create jbrowse folder {}".format(self.out_path) | 37 self.chromSizesFile = None |
| 38 | |
| 39 | |
| 40 # Set all the missing variables of this class, and create physically the folders/files | |
| 41 self.rootAssemblyHub = self.__createAssemblyHub__(extra_files_path=extra_files_path) | |
| 42 # Init the Datatype | |
| 43 Datatype.pre_init(self.reference_genome, self.chromSizesFile, | |
| 44 self.extra_files_path, self.tool_directory, | |
| 45 self.mySpecieFolderPath, self.myTracksFolderPath, self.myBinaryFolderPath, self.trackType) | |
| 46 | |
| 47 self._prepareRefseq() | |
| 48 self.trackList = os.path.join(self.mySpecieFolderPath, "trackList.json") | |
| 49 self._createTrackList() | |
| 50 | |
| 51 self.myTrackStyle = TrackStyles(self.tool_directory, self.mySpecieFolderPath, self.trackList) | |
| 52 #self.cssFolderPath = os.path.join(self.mySpecieFolderPath, 'css') | |
| 53 #self.cssFilePath = os.path.join(self.cssFolderPath, 'custom_track_styles.css') | |
| 54 self.logger = logging.getLogger(__name__) | |
| 55 | |
| 31 | 56 |
| 32 def createHub(self): | 57 |
| 33 self.prepareRefseq() | 58 def addTrack(self, trackDbObject): |
| 34 for input_file in self.input_files: | 59 if trackDbObject['dataType'].lower() == 'bam': |
| 35 self.addTrack(input_file) | 60 #new_track = subprocess.Popen(['echo', trackDbObject['options']], stdout=subprocess.PIPE) |
| 36 self.indexName() | 61 #subprocess.call(['add-track-json.pl', json_file], stdin=new_track.stdout) |
| 37 slink = self.makeArchive() | 62 subtools.add_track_json(self.trackList, trackDbObject['options']) |
| 38 self.outHtml(slink) | 63 #subtools.add_track_json(self.trackList, trackDbObject['track_json']) |
| 64 elif trackDbObject['dataType'].lower() == 'bigwig': | |
| 65 subtools.add_track_json(self.trackList, trackDbObject['options']) | |
| 66 else: | |
| 67 if trackDbObject['trackType'] == 'HTMLFeatures': | |
| 68 self._customizeHTMLFeature(trackDbObject) | |
| 69 subtools.flatfile_to_json(trackDbObject['trackDataURL'], trackDbObject['dataType'], trackDbObject['trackType'], trackDbObject['trackLabel'], self.mySpecieFolderPath, trackDbObject['options']) | |
| 70 | |
| 71 | |
| 72 def terminate(self, debug=False): | |
| 73 """ Write html file """ | |
| 74 self._indexName() | |
| 75 if not debug: | |
| 76 self._removeRaw() | |
| 77 #self._makeArchive() | |
| 78 self._outHtml() | |
| 39 print "Success!\n" | 79 print "Success!\n" |
| 40 | 80 |
| 41 def prepareRefseq(self): | 81 |
| 42 try: | 82 def _customizeHTMLFeature(self, trackDbObject): |
| 83 if trackDbObject['options']: | |
| 84 subfeatures = trackDbObject['options'].get('subfeatureClasses') | |
| 85 feature_color = trackDbObject['options']['feature_color'] | |
| 86 if subfeatures: | |
| 87 for key, value in subfeatures.items(): | |
| 88 self.myTrackStyle.addCustomColor(value, feature_color) | |
| 89 else: | |
| 90 customizedFeature = santitizer.sanitize_name(trackDbObject['trackLabel']) | |
| 91 clientConfig = json.loads(trackDbObject['options']['clientConfig']) | |
| 92 clientConfig['renderClassName'] = customizedFeature | |
| 93 trackDbObject['options']['clientConfig'] = json.dumps(clientConfig) | |
| 94 self.myTrackStyle.addCustomColor(customizedFeature, feature_color) | |
| 95 | |
| 96 def _removeRaw(self): | |
| 97 if os.path.exists(self.myTracksFolderPath): | |
| 98 shutil.rmtree(self.myTracksFolderPath) | |
| 99 | |
| 100 def _createTrackList(self): | |
| 101 if not os.path.exists(self.trackList): | |
| 102 os.mknod(self.trackList) | |
| 103 | |
| 104 def _prepareRefseq(self): | |
| 105 subtools.prepare_refseqs(self.reference_genome.false_path, self.mySpecieFolderPath) | |
| 106 #try: | |
| 43 #print os.path.join(self.tool_dir, 'prepare-refseqs.pl') + ", '--fasta', " + self.reference +", '--out', self.json])" | 107 #print os.path.join(self.tool_dir, 'prepare-refseqs.pl') + ", '--fasta', " + self.reference +", '--out', self.json])" |
| 44 subprocess.call(['prepare-refseqs.pl', '--fasta', self.reference, '--out', self.json]) | 108 #subprocess.call(['prepare-refseqs.pl', '--fasta', self.reference_genome.false_path, '--out', self.mySpecieFolderPath]) |
| 45 except OSError as e: | 109 #except OSError as e: |
| 46 print "Cannot prepare reference error({0}): {1}".format(e.errno, e.strerror) | 110 #print "Cannot prepare reference error({0}): {1}".format(e.errno, e.strerror) |
| 47 #TODO: hard coded the bam and bigwig tracks. Need to allow users to customize the settings | 111 |
| 48 def addTrack(self, track): | 112 def _indexName(self): |
| 49 #print "false_path" , track['false_path'] | 113 #subprocess.call(['generate-names.pl', '-v', '--out', self.mySpecieFolderPath]) |
| 50 if track['false_path'] in self.metaData.keys(): | 114 subtools.generate_names(self.mySpecieFolderPath) |
| 51 metadata = self.metaData[track['false_path']] | |
| 52 else: | |
| 53 metadata = {} | |
| 54 self.SetMetadata(track, metadata) | |
| 55 if track['dataType'] == 'bam': | |
| 56 self.Bam(track, metadata) | |
| 57 # print "add bam track\n" | |
| 58 elif track['dataType'] == 'bigwig': | |
| 59 self.BigWig(track, metadata) | |
| 60 else: | |
| 61 flat_file = os.path.join(self.raw, track['fileName']) | |
| 62 if track['dataType'] == 'bed': | |
| 63 subprocess.call(['flatfile-to-json.pl', '--bed', flat_file, '--trackType', metadata['type'], '--trackLabel', metadata['label'], '--Config', '{"category" : "%s"}' % metadata['category'], '--clientConfig', '{"color" : "%s"}' % metadata['color'], '--out', self.json]) | |
| 64 elif track['dataType'] == 'bedSpliceJunctions' or track['dataType'] == 'gtf' or track['dataType'] == 'blastxml': | |
| 65 subprocess.call(['flatfile-to-json.pl', '--gff', flat_file, '--trackType', metadata['type'], '--trackLabel', metadata['label'], '--Config', '{"glyph": "JBrowse/View/FeatureGlyph/Segments", "category" : "%s"}' % metadata['category'], '--clientConfig', '{"color" : "%s"}' % metadata['color'], '--out', self.json]) | |
| 66 elif track['dataType'] == 'gff3_transcript': | |
| 67 subprocess.call(['flatfile-to-json.pl', '--gff', flat_file, '--trackType', metadata['type'], '--trackLabel', metadata['label'], '--Config', '{"transcriptType": "transcript", "category" : "%s"}' % metadata['category'], '--clientConfig', '{"color" : "%s"}' % metadata['color'], '--out', self.json]) | |
| 68 else: | |
| 69 subprocess.call(['flatfile-to-json.pl', '--gff', flat_file, '--trackType', metadata['type'], '--trackLabel', metadata['label'], '--Config', '{"category" : "%s"}' % metadata['category'], '--clientConfig', '{"color" : "%s"}' % metadata['color'], '--out', self.json]) | |
| 70 | |
| 71 def indexName(self): | |
| 72 subprocess.call(['generate-names.pl', '-v', '--out', self.json]) | |
| 73 print "finished name index \n" | 115 print "finished name index \n" |
| 74 | 116 |
| 75 def makeArchive(self): | 117 def _outHtml(self): |
| 76 file_dir = os.path.abspath(self.outfile) | 118 mylookup = TemplateLookup(directories=[os.path.join(self.tool_directory, 'templates')], |
| 77 source_dir = os.path.dirname(file_dir) | 119 output_encoding='utf-8', encoding_errors='replace') |
| 78 folder_name = os.path.basename(self.outfolder) | 120 htmlTemplate = mylookup.get_template("display.txt") |
| 79 source_name = os.path.basename(self.out_path) | |
| 80 source = os.path.join(source_dir, folder_name, source_name) | |
| 81 slink = source.replace('/', '_') | |
| 82 slink = os.path.join('/var/www/html/JBrowse-1.12.1/data', slink) | |
| 83 try: | |
| 84 if os.path.islink(slink): | |
| 85 os.unlink(slink) | |
| 86 except OSError as oserror: | |
| 87 print "Cannot create symlink to the data({0}): {1}".format(oserror.errno, oserror.strerror) | |
| 88 os.symlink(source, slink) | |
| 89 return slink | |
| 90 | |
| 91 def outHtml(self, slink): | |
| 92 with open(self.outfile, 'w') as htmlfile: | |
| 93 htmlstr = 'The JBrowse Hub is created: <br>' | |
| 94 url = self.jbrowse_host + "/JBrowse-1.12.1/index.html?data=%s" | |
| 95 jbrowse_hub = '<li><a href = "%s" target="_blank">View JBrowse Hub</a></li>' % url | |
| 96 link_name = os.path.basename(slink) | |
| 97 relative_path = os.path.join('data', link_name + '/json') | |
| 98 htmlstr += jbrowse_hub % relative_path | |
| 99 htmlfile.write(htmlstr) | |
| 100 | 121 |
| 101 def createTrackList(self): | 122 with open(self.outputFile, 'w') as htmlfile: |
| 102 trackList = os.path.join(self.json, "trackList.json") | 123 htmlMakoRendered = htmlTemplate.render( |
| 103 if not os.path.exists(trackList): | 124 species_folder = os.path.relpath(self.mySpecieFolderPath, self.extra_files_path), |
| 104 os.mknod(trackList) | 125 trackList = os.path.relpath(self.trackList, self.extra_files_path) |
| 105 | 126 ) |
| 106 def Bam(self, track, metadata): | 127 htmlfile.write(htmlMakoRendered) |
| 107 #create trackList.json if not exist | 128 #with open(self.outputFile, 'w') as htmlfile: |
| 108 self.createTrackList() | 129 # htmlstr = 'The new Organism "%s" is created on Apollo: <br>' % self.genome_name |
| 109 json_file = os.path.join(self.json, "trackList.json") | 130 # jbrowse_hub = '<li><a href = "%s" target="_blank">View JBrowse Hub on Apollo</a></li>' % host_name |
| 110 bam_track = dict() | 131 # htmlstr += jbrowse_hub |
| 111 bam_track['type'] = 'JBrowse/View/Track/Alignments2' | 132 # htmlfile.write(htmlstr) |
| 112 bam_track['storeClass'] = 'JBrowse/Store/SeqFeature/BAM' | 133 |
| 113 bam_track['urlTemplate'] = os.path.join('../raw', track['fileName']) | |
| 114 bam_track['baiUrlTemplate'] = os.path.join('../raw', track['index']) | |
| 115 bam_track['label'] = metadata['label'] | |
| 116 bam_track['category'] = metadata['category'] | |
| 117 bam_track = json.dumps(bam_track) | |
| 118 #Use add-track-json.pl to add bam track to json file | |
| 119 new_track = subprocess.Popen(['echo', bam_track], stdout=subprocess.PIPE) | |
| 120 subprocess.call(['add-track-json.pl', json_file], stdin=new_track.stdout) | |
| 121 | |
| 122 def BigWig(self, track, metadata): | |
| 123 #create trackList.json if not exist | |
| 124 self.createTrackList() | |
| 125 json_file = os.path.join(self.json, "trackList.json") | |
| 126 bigwig_track = dict() | |
| 127 bigwig_track['urlTemplate'] = os.path.join('../raw', track['fileName']) | |
| 128 bigwig_track['type'] = 'JBrowse/View/Track/Wiggle/XYPlot' | |
| 129 bigwig_track['storeClass'] = 'JBrowse/Store/SeqFeature/BigWig' | |
| 130 bigwig_track['label'] = metadata['label'] | |
| 131 bigwig_track['style'] = metadata['style'] | |
| 132 bigwig_track['category'] = metadata['category'] | |
| 133 bigwig_track = json.dumps(bigwig_track) | |
| 134 #Use add-track-json.pl to add bigwig track to json file | |
| 135 new_track = subprocess.Popen(['echo', bigwig_track], stdout=subprocess.PIPE) | |
| 136 #output = new_track.communicate()[0] | |
| 137 subprocess.call(['add-track-json.pl', json_file], stdin=new_track.stdout) | |
| 138 | |
| 139 #If the metadata is not set, use the default value | |
| 140 def SetMetadata(self, track, metadata): | |
| 141 if 'label' not in metadata.keys() or metadata['label'] == '': | |
| 142 metadata['label'] = track['fileName'] | |
| 143 if 'color' not in metadata.keys() or metadata['color'] == '': | |
| 144 metadata['color'] = "#daa520" | |
| 145 if track['dataType'] == 'bigwig': | |
| 146 if 'style' not in metadata.keys(): | |
| 147 metadata['style'] = {} | |
| 148 if 'pos_color' not in metadata['style'] or metadata['style']['pos_color'] == '': | |
| 149 metadata['style']['pos_color'] = "#FFA600" | |
| 150 if 'neg_color' not in metadata['style'] or metadata['style']['neg_color'] == '': | |
| 151 metadata['style']['neg_color'] = "#005EFF" | |
| 152 if 'category' not in metadata.keys() or metadata['category'] == '': | |
| 153 metadata['category'] = "Default group" | |
| 154 if track['dataType'] == 'blastxml': | |
| 155 metadata['type'] = "G-OnRamp_plugin/BlastAlignment" | |
| 156 elif track['dataType'] == 'bigpsl': | |
| 157 metadata['type'] = "G-OnRamp_plugin/BlatAlignment" | |
| 158 elif track['dataType'] == 'gff3_transcript' or track['dataType'] == 'gff3_mrna': | |
| 159 metadata['type'] = "G-OnRamp_plugin/GenePred" | |
| 160 else: | |
| 161 metadata['type'] = "CanvasFeatures" | |
| 162 | 134 |
| 163 | 135 |
| 136 def __createAssemblyHub__(self, extra_files_path): | |
| 137 # Get all necessaries infos first | |
| 138 # 2bit file creation from input fasta | |
| 164 | 139 |
| 165 | 140 # baseNameFasta = os.path.basename(fasta_file_name) |
| 141 # suffixTwoBit, extensionTwoBit = os.path.splitext(baseNameFasta) | |
| 142 # nameTwoBit = suffixTwoBit + '.2bit' | |
| 143 twoBitFile = tempfile.NamedTemporaryFile(bufsize=0) | |
| 144 subtools.faToTwoBit(self.reference_genome.false_path, twoBitFile.name) | |
| 166 | 145 |
| 146 # Generate the twoBitInfo | |
| 147 twoBitInfoFile = tempfile.NamedTemporaryFile(bufsize=0) | |
| 148 subtools.twoBitInfo(twoBitFile.name, twoBitInfoFile.name) | |
| 167 | 149 |
| 150 # Then we get the output to generate the chromSizes | |
| 151 self.chromSizesFile = tempfile.NamedTemporaryFile(bufsize=0, suffix=".chrom.sizes") | |
| 152 subtools.sortChromSizes(twoBitInfoFile.name, self.chromSizesFile.name) | |
| 168 | 153 |
| 154 # We can get the biggest scaffold here, with chromSizesFile | |
| 155 with open(self.chromSizesFile.name, 'r') as chrom_sizes: | |
| 156 # TODO: Check if exists | |
| 157 self.default_pos = chrom_sizes.readline().split()[0] | |
| 158 | |
| 159 # TODO: Manage to put every fill Function in a file dedicated for reading reasons | |
| 160 # Create the root directory | |
| 161 myHubPath = os.path.join(extra_files_path, "myHub") | |
| 162 if not os.path.exists(myHubPath): | |
| 163 os.makedirs(myHubPath) | |
| 164 | |
| 165 # Create the specie folder | |
| 166 # TODO: Generate the name depending on the specie | |
| 167 mySpecieFolderPath = os.path.join(myHubPath, self.genome_name) | |
| 168 if not os.path.exists(mySpecieFolderPath): | |
| 169 os.makedirs(mySpecieFolderPath) | |
| 170 self.mySpecieFolderPath = mySpecieFolderPath | |
| 171 | |
| 172 # We create the 2bit file while we just created the specie folder | |
| 173 #self.twoBitName = self.genome_name + ".2bit" | |
| 174 #self.two_bit_final_path = os.path.join(self.mySpecieFolderPath, self.twoBitName) | |
| 175 #shutil.copyfile(twoBitFile.name, self.two_bit_final_path) | |
| 176 | |
| 177 # Create the folder tracks into the specie folder | |
| 178 tracksFolderPath = os.path.join(mySpecieFolderPath, "raw") | |
| 179 if not os.path.exists(tracksFolderPath): | |
| 180 os.makedirs(tracksFolderPath) | |
| 181 self.myTracksFolderPath = tracksFolderPath | |
| 182 | |
| 183 myBinaryFolderPath = os.path.join(mySpecieFolderPath, 'bbi') | |
| 184 if not os.path.exists(myBinaryFolderPath): | |
| 185 os.makedirs(myBinaryFolderPath) | |
| 186 self.myBinaryFolderPath = myBinaryFolderPath | |
| 187 | |
| 188 return myHubPath |
