From e5e5cebe6b07da9ccbf33f04f86c4add4da1c888 Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Thu, 23 Feb 2012 12:23:36 -0500 Subject: [PATCH] Enable visualization of ENCODE peak tracks. Create 'encodepeak' datatype and add data providers for new datatype. --- datatypes_conf.xml.sample | 5 + .../encodepeak_to_bgzip_converter.xml | 19 +++ .../encodepeak_to_summary_tree_converter.xml | 20 +++ .../encodepeak_to_tabix_converter.xml | 20 +++ lib/galaxy/datatypes/interval.py | 30 +++++ .../visualization/tracks/data_providers.py | 126 +++++++++++++++++- 6 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 lib/galaxy/datatypes/converters/encodepeak_to_bgzip_converter.xml create mode 100644 lib/galaxy/datatypes/converters/encodepeak_to_summary_tree_converter.xml create mode 100644 lib/galaxy/datatypes/converters/encodepeak_to_tabix_converter.xml diff --git a/datatypes_conf.xml.sample b/datatypes_conf.xml.sample index c96d75b3021..5618dc6a4d3 100644 --- a/datatypes_conf.xml.sample +++ b/datatypes_conf.xml.sample @@ -130,6 +130,11 @@ + + + + + diff --git a/lib/galaxy/datatypes/converters/encodepeak_to_bgzip_converter.xml b/lib/galaxy/datatypes/converters/encodepeak_to_bgzip_converter.xml new file mode 100644 index 00000000000..0779e6e7574 --- /dev/null +++ b/lib/galaxy/datatypes/converters/encodepeak_to_bgzip_converter.xml @@ -0,0 +1,19 @@ + diff --git a/lib/galaxy/datatypes/converters/encodepeak_to_summary_tree_converter.xml b/lib/galaxy/datatypes/converters/encodepeak_to_summary_tree_converter.xml new file mode 100644 index 00000000000..fc5db2e4bde --- /dev/null +++ b/lib/galaxy/datatypes/converters/encodepeak_to_summary_tree_converter.xml @@ -0,0 +1,20 @@ + diff --git a/lib/galaxy/datatypes/converters/encodepeak_to_tabix_converter.xml b/lib/galaxy/datatypes/converters/encodepeak_to_tabix_converter.xml new file mode 100644 index 00000000000..470dfb9936e --- /dev/null +++ b/lib/galaxy/datatypes/converters/encodepeak_to_tabix_converter.xml @@ -0,0 +1,20 @@ + diff --git a/lib/galaxy/datatypes/interval.py b/lib/galaxy/datatypes/interval.py index 0d2ccc4cd3d..5706aa77324 100644 --- a/lib/galaxy/datatypes/interval.py +++ b/lib/galaxy/datatypes/interval.py @@ -1263,6 +1263,36 @@ class CustomTrack ( Tabular ): except: return False return True + +class ENCODEPeak( Interval ): + ''' + Human ENCODE peak format. There are both broad and narrow peak formats. + Formats are very similar; narrow peak has an additional column, though. + + Broad peak ( http://genome.ucsc.edu/FAQ/FAQformat#format13 ): + This format is used to provide called regions of signal enrichment based + on pooled, normalized (interpreted) data. It is a BED 6+3 format. + + Narrow peak http://genome.ucsc.edu/FAQ/FAQformat#format12 and : + This format is used to provide called peaks of signal enrichment based on + pooled, normalized (interpreted) data. It is a BED6+4 format. + ''' + + file_ext = "encodepeak" + column_names = [ 'Chrom', 'Start', 'End', 'Name', 'Score', 'Strand', 'SignalValue', 'pValue', 'qValue', 'Peak' ] + + """Add metadata elements""" + MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter ) + MetadataElement( name="startCol", default=2, desc="Start column", param=metadata.ColumnParameter ) + MetadataElement( name="endCol", default=3, desc="End column", param=metadata.ColumnParameter ) + MetadataElement( name="strandCol", desc="Strand column (click box & select)", param=metadata.ColumnParameter, optional=True, no_value=0 ) + MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False ) + + def sniff( self, filename ): + return Exception( "Unimplemented Function" ) + + def get_track_type( self ): + return "FeatureTrack", {"data": "tabix", "index": "summary_tree"} if __name__ == '__main__': import doctest, sys diff --git a/lib/galaxy/visualization/tracks/data_providers.py b/lib/galaxy/visualization/tracks/data_providers.py index f562563e985..0468631cf22 100644 --- a/lib/galaxy/visualization/tracks/data_providers.py +++ b/lib/galaxy/visualization/tracks/data_providers.py @@ -19,7 +19,7 @@ from galaxy.util.lrucache import LRUCache from galaxy.visualization.tracks.summary import * import galaxy_utils.sequence.vcf from galaxy.datatypes.tabular import Vcf -from galaxy.datatypes.interval import Bed, Gff, Gtf +from galaxy.datatypes.interval import Bed, Gff, Gtf, ENCODEPeak from pysam import csamtools, ctabix @@ -288,7 +288,7 @@ class BedDataProvider( TracksDataProvider ): Provides """ # Build data to return. Payload format is: - # [ , , , , , , , + # [ , , , , , , # , ] # # First three entries are mandatory, others are optional. @@ -965,6 +965,126 @@ class GFFDataProvider( TracksDataProvider ): return { 'data': results, 'message': message } + +# +# -- ENCODE Peak data providers. +# + +class ENCODEPeakDataProvider( TracksDataProvider ): + """ + Abstract class that processes ENCODEPeak data from native format to payload format. + + Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ] + """ + + def get_iterator( self, chrom, start, end ): + raise "Unimplemented Method" + + def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ): + """ + Provides + """ + + ## FIXMEs: + # (1) should be able to unify some of this code with BedDataProvider.process_data + # (2) are optional number of parameters supported? + + # Build data to return. Payload format is: + # [ , , , , , , + # , ] + # + # First three entries are mandatory, others are optional. + # + no_detail = ( "no_detail" in kwargs ) + rval = [] + message = None + for count, line in enumerate( iterator ): + if count < start_val: + continue + if max_vals and count-start_val >= max_vals: + message = ERROR_MAX_VALS % ( max_vals, "features" ) + break + + feature = line.split() + length = len( feature ) + + # Feature initialization. + payload = [ + # GUID is just a hash of the line + hash( line ), + # Add start, end. + int( feature[1] ), + int( feature[2] ) + ] + + if no_detail: + rval.append( payload ) + continue + + # Extend with additional data. + payload.extend( [ + # Add name, strand. + feature[3], + feature[5], + # Thick start, end are feature start, end for now. + int( feature[1] ), + int( feature[2] ), + # No blocks. + None, + # Filtering data: Score, signalValue, pValue, qValue. + float( feature[4] ), + float( feature[6] ), + float( feature[7] ), + float( feature[8] ) + ] ) + + rval.append( payload ) + + return { 'data': rval, 'message': message } + + def write_data_to_file( self, chrom, start, end, filename ): + iterator = self.get_iterator( chrom, start, end ) + out = open( filename, "w" ) + for line in iterator: + out.write( "%s\n" % line ) + out.close() + +class ENCODEPeakTabixDataProvider( TabixDataProvider, ENCODEPeakDataProvider ): + """ + Provides data from an ENCODEPeak dataset indexed via tabix. + """ + + def get_filters( self ): + """ + Returns filters for dataset. + """ + # HACK: first 8 fields are for drawing, so start filter column index at 9. + filter_col = 8 + filters = [] + filters.append( { 'name': 'Score', + 'type': 'number', + 'index': filter_col, + 'tool_id': 'Filter1', + 'tool_exp_name': 'c6' } ) + filter_col += 1 + filters.append( { 'name': 'Signal Value', + 'type': 'number', + 'index': filter_col, + 'tool_id': 'Filter1', + 'tool_exp_name': 'c7' } ) + filter_col += 1 + filters.append( { 'name': 'pValue', + 'type': 'number', + 'index': filter_col, + 'tool_id': 'Filter1', + 'tool_exp_name': 'c8' } ) + filter_col += 1 + filters.append( { 'name': 'qValue', + 'type': 'number', + 'index': filter_col, + 'tool_id': 'Filter1', + 'tool_exp_name': 'c9' } ) + return filters # # -- Helper methods. -- @@ -974,7 +1094,7 @@ class GFFDataProvider( TracksDataProvider ): # type. First key is converted dataset type; if result is another dict, second key # is original dataset type. TODO: This needs to be more flexible. dataset_type_name_to_data_provider = { - "tabix": { Vcf: VcfTabixDataProvider, Bed: BedTabixDataProvider, "default" : TabixDataProvider }, + "tabix": { Vcf: VcfTabixDataProvider, Bed: BedTabixDataProvider, ENCODEPeak: ENCODEPeakTabixDataProvider, "default" : TabixDataProvider }, "interval_index": IntervalIndexDataProvider, "bai": BamDataProvider, "bam": SamDataProvider,