From 6bce16592ea63e547de2eef2afea803d65a56fb3 Mon Sep 17 00:00:00 2001 From: Daniel Blankenberg Date: Thu, 1 Apr 2010 13:08:48 -0400 Subject: [PATCH] Add bed6 and bed12 datatypes, which are subclasses of bedstrict; converters are available to turn any interval datatype into these types. Change GeneTrack Indexer tool and converter to use bed6 as input. --- datatypes_conf.xml.sample | 7 +- display_applications/genetrack.xml | 2 +- .../converters/bed_to_genetrack_converter.xml | 4 +- .../interval_to_bed12_converter.xml | 15 ++++ .../converters/interval_to_bed6_converter.xml | 15 ++++ .../interval_to_bedstrict_converter.py | 81 ++++++++++++++----- lib/galaxy/datatypes/interval.py | 10 +++ tools/genetrack/genetrack_indexer.xml | 4 +- 8 files changed, 111 insertions(+), 27 deletions(-) create mode 100644 lib/galaxy/datatypes/converters/interval_to_bed12_converter.xml create mode 100644 lib/galaxy/datatypes/converters/interval_to_bed6_converter.xml diff --git a/datatypes_conf.xml.sample b/datatypes_conf.xml.sample index 896951b92f0..98ce89590c3 100644 --- a/datatypes_conf.xml.sample +++ b/datatypes_conf.xml.sample @@ -13,11 +13,14 @@ - + + + + @@ -49,6 +52,8 @@ + + diff --git a/display_applications/genetrack.xml b/display_applications/genetrack.xml index 3b71ae77376..3d250bdafa4 100644 --- a/display_applications/genetrack.xml +++ b/display_applications/genetrack.xml @@ -1,7 +1,7 @@ http://genetrack.g2.bx.psu.edu/galaxy?filename=${encoded_filename.qp}&hashkey=${hash_key.qp}&input=${qp(str($genetrack_file.id))}&GALAXY_URL=${galaxy_url.qp} - + ${BASE_URL}/tool_runner?tool_id=predict2genetrack diff --git a/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml b/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml index 420c56768e7..fcd6fb1a276 100644 --- a/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml +++ b/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ Using a shift of 0, but tool allows specifying... bed_to_genetrack_converter.py -i $input1 -o $output1 -s 0 -v 0 -f BED -x - + diff --git a/lib/galaxy/datatypes/converters/interval_to_bed12_converter.xml b/lib/galaxy/datatypes/converters/interval_to_bed12_converter.xml new file mode 100644 index 00000000000..7e1f96b4dce --- /dev/null +++ b/lib/galaxy/datatypes/converters/interval_to_bed12_converter.xml @@ -0,0 +1,15 @@ + + + + interval_to_bedstrict_converter.py $output1 $input1 ${input1.metadata.chromCol} ${input1.metadata.startCol} ${input1.metadata.endCol} ${input1.metadata.strandCol} ${input1.metadata.nameCol} ${input1.extension} 12 + + + + + + + + + + + diff --git a/lib/galaxy/datatypes/converters/interval_to_bed6_converter.xml b/lib/galaxy/datatypes/converters/interval_to_bed6_converter.xml new file mode 100644 index 00000000000..0353fb93efe --- /dev/null +++ b/lib/galaxy/datatypes/converters/interval_to_bed6_converter.xml @@ -0,0 +1,15 @@ + + + + interval_to_bedstrict_converter.py $output1 $input1 ${input1.metadata.chromCol} ${input1.metadata.startCol} ${input1.metadata.endCol} ${input1.metadata.strandCol} ${input1.metadata.nameCol} ${input1.extension} 6 + + + + + + + + + + + diff --git a/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py b/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py index 4445a28b103..97e6f2bedfc 100644 --- a/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py +++ b/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py @@ -12,6 +12,27 @@ def stop_err( msg ): sys.stderr.write( msg ) sys.exit() +def force_bed_field_count( fields, region_count, force_num_columns ): + if force_num_columns >= 4 and len( fields ) < 4: + fields.append( 'region_%i' % ( region_count ) ) + if force_num_columns >= 5 and len( fields ) < 5: + fields.append( '0' ) + if force_num_columns >= 6 and len( fields ) < 6: + fields.append( '+' ) + if force_num_columns >= 7 and len( fields ) < 7: + fields.append( fields[1] ) + if force_num_columns >= 8 and len( fields ) < 8: + fields.append( fields[2] ) + if force_num_columns >= 9 and len( fields ) < 9: + fields.append( '0' ) + if force_num_columns >= 10 and len( fields ) < 10: + fields.append( '0' ) + if force_num_columns >= 11 and len( fields ) < 11: + fields.append( ',' ) + if force_num_columns >= 12 and len( fields ) < 12: + fields.append( ',' ) + return fields[:force_num_columns] + def __main__(): output_name = sys.argv[1] input_name = sys.argv[2] @@ -39,6 +60,10 @@ def __main__(): extension = sys.argv[8] except: extension = 'interval' #default extension + try: + force_num_columns = int( sys.argv[9] ) + except: + force_num_columns = None skipped_lines = 0 first_skipped_line = None @@ -47,40 +72,52 @@ def __main__(): #does file already conform to bed strict? #if so, we want to keep extended columns, otherwise we'll create a generic 6 column bed file strict_bed = True - if extension in [ 'bed', 'bedstrict' ] and ( chromCol, startCol, endCol, nameCol, strandCol ) == ( 0, 1, 2, 3, 5 ): + if extension in [ 'bed', 'bedstrict', 'bed6', 'bed12' ] and ( chromCol, startCol, endCol) == ( 0, 1, 2) and ( nameCol < 0 or nameCol == 3 ) and ( strandCol < 0 or strandCol == 5 ): for count, line in enumerate( open( input_name ) ): - line = line.strip() + line = line.rstrip( '\n\r' ) if line == "" or line.startswith("#"): skipped_lines += 1 if first_skipped_line is None: first_skipped_line = count + 1 continue fields = line.split('\t') + assert len( fields ) >= 3, 'A BED file requires at least 3 columns' #we can't fix this try: if len(fields) > 12: strict_bed = False break - if len(fields) > 6: - int(fields[6]) - if len(fields) > 7: - int(fields[7]) - if len(fields) > 8: - if int(fields[8]) != 0: - strict_bed = False - break - if len(fields) > 9: - int(fields[9]) - if len(fields) > 10: - fields2 = fields[10].rstrip(",").split(",") #remove trailing comma and split on comma - for field in fields2: - int(field) - if len(fields) > 11: - fields2 = fields[11].rstrip(",").split(",") #remove trailing comma and split on comma + #name (fields[3]) can be anything, no verification needed + if len( fields ) > 4: + float( fields[4] ) #score - A score between 0 and 1000. If the track line useScore attribute is set to 1 for this annotation data set, the score value will determine the level of gray in which this feature is displayed (higher numbers = darker gray). + if len( fields ) > 5: + assert fields[5] in [ '+', '-' ], 'Invalid strand' #strand - Defines the strand - either '+' or '-'. + if len( fields ) > 6: + int( fields[6] ) #thickStart - The starting position at which the feature is drawn thickly (for example, the start codon in gene displays). + if len( fields ) > 7: + int( fields[7] ) #thickEnd - The ending position at which the feature is drawn thickly (for example, the stop codon in gene displays). + if len( fields ) > 8: + if fields[8] != '0': #itemRgb - An RGB value of the form R,G,B (e.g. 255,0,0). If the track line itemRgb attribute is set to "On", this RBG value will determine the display color of the data contained in this BED line. NOTE: It is recommended that a simple color scheme (eight colors or less) be used with this attribute to avoid overwhelming the color resources of the Genome Browser and your Internet browser. + fields2 = fields[8].split( ',' ) + assert len( fields2 ) == 3, 'RGB value must be 0 or have length of 3' for field in fields2: - int(field) + int( field ) #rgb values are integers + if len( fields ) > 9: + int( fields[9] ) #blockCount - The number of blocks (exons) in the BED line. + if len( fields ) > 10: + if fields[10] != ',': #blockSizes - A comma-separated list of the block sizes. The number of items in this list should correspond to blockCount. + fields2 = fields[10].rstrip( "," ).split( "," ) #remove trailing comma and split on comma + for field in fields2: + int( field ) + if len( fields ) > 11: + if fields[11] != ',': #blockStarts - A comma-separated list of block starts. All of the blockStart positions should be calculated relative to chromStart. The number of items in this list should correspond to blockCount. + fields2 = fields[11].rstrip( "," ).split( "," ) #remove trailing comma and split on comma + for field in fields2: + int( field ) except: strict_bed = False break + if force_num_columns is not None and len( fields ) != force_num_columns: + line = '\t'.join( force_bed_field_count( fields, count, force_num_columns ) ) out.write( "%s\n" % line ) else: strict_bed = False @@ -100,8 +137,10 @@ def __main__(): except: name = "region_%i" % count try: - - out.write( "%s\t%i\t%i\t%s\t%i\t%s\n" % ( region.chrom, region.start, region.end, name, 0, region.strand ) ) + fields = map( str, [ region.chrom, region.start, region.end, name, 0, region.strand ] ) + if force_num_columns is not None and len( fields ) != force_num_columns: + fields = force_bed_field_count( fields, count, force_num_columns ) + out.write( "%s\n" % '\t'.join( fields ) ) except: skipped_lines += 1 if first_skipped_line is None: diff --git a/lib/galaxy/datatypes/interval.py b/lib/galaxy/datatypes/interval.py index c6e1b892d41..4b7e5c2afe1 100644 --- a/lib/galaxy/datatypes/interval.py +++ b/lib/galaxy/datatypes/interval.py @@ -536,6 +536,16 @@ class BedStrict( Bed ): def sniff( self, filename ): return False #NOTE: This would require aggressively validating the entire file +class Bed6( BedStrict ): + """Tab delimited data in strict BED format - no non-standard columns allowed; column count forced to 6""" + + file_ext = "bed6" + +class Bed12( BedStrict ): + """Tab delimited data in strict BED format - no non-standard columns allowed; column count forced to 12""" + + file_ext = "bed12" + class _RemoteCallMixin: def _get_remote_call_url( self, redirect_url, site_name, dataset, type, app, base_url ): """Retrieve the URL to call out to an external site and retrieve data. diff --git a/tools/genetrack/genetrack_indexer.xml b/tools/genetrack/genetrack_indexer.xml index 79cf9bac192..aae5e313779 100644 --- a/tools/genetrack/genetrack_indexer.xml +++ b/tools/genetrack/genetrack_indexer.xml @@ -1,4 +1,4 @@ - + on a BED file @@ -8,7 +8,7 @@ - +