details: http://www.bx.psu.edu/hg/galaxy/rev/f13d85256124 changeset: 3521:f13d85256124 user: Dan Blankenberg <dan@bx.psu.edu> date: Thu Mar 11 14:35:36 2010 -0500 description: Display Application framework enhancements. Add the ability for display applications to be populated dynamically based upon the content of (e.g. tabular) files. Display application links can be filtered by various attributes, including e.g. dataset dbkey matching from field in a file or an attribute matching a Galaxy application configuration setting. Param and Data URL values can now be generated dynamically, allowing e.g unique base filenames to be created and used. See updated xml configurations in /display_applications/ for examples of syntax. diffstat: datatypes_conf.xml.sample | 9 +- display_applications/ucsc/bam.xml | 34 +++++- display_applications/ucsc/interval_as_bed.xml | 63 +++++++++++- lib/galaxy/datatypes/data.py | 9 + lib/galaxy/datatypes/display_applications/application.py | 78 ++++++++++++++- lib/galaxy/datatypes/display_applications/parameters.py | 13 +- lib/galaxy/datatypes/registry.py | 34 ++++-- lib/galaxy/model/__init__.py | 3 + templates/root/history_common.mako | 2 +- tool-data/shared/bx/bx_build_sites.txt | 2 +- 10 files changed, 205 insertions(+), 42 deletions(-) diffs (468 lines): diff -r 262b16c8e277 -r f13d85256124 datatypes_conf.xml.sample --- a/datatypes_conf.xml.sample Thu Mar 11 13:51:53 2010 -0500 +++ b/datatypes_conf.xml.sample Thu Mar 11 14:35:36 2010 -0500 @@ -15,10 +15,7 @@ <!-- <display file="ucsc/interval_as_bed.xml" /> --> <display file="genetrack.xml" /> </datatype> - <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict"> - <display file="ucsc/interval_as_bed.xml" /> - <display file="genetrack.xml" /> - </datatype> + <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict" /> <datatype extension="binseq.zip" type="galaxy.datatypes.binary:Binseq" mimetype="application/zip" display_in_upload="true"/> <datatype extension="len" type="galaxy.datatypes.chrominfo:ChromInfo" display_in_upload="true"> <!-- no converters yet --> @@ -51,8 +48,8 @@ <converter file="interval_to_bed_converter.xml" target_datatype="bed"/> <converter file="interval_to_bedstrict_converter.xml" target_datatype="bedstrict"/> <indexer file="interval_awk.xml" /> - <!-- <display file="ucsc/interval_as_bed.xml" /> --> - <display file="genetrack.xml" /> + <!-- <display file="ucsc/interval_as_bed.xml" inherit="True" /> --> + <display file="genetrack.xml" inherit="True"/> </datatype> <datatype extension="jpg" type="galaxy.datatypes.images:Image" mimetype="image/jpeg"/> <datatype extension="laj" type="galaxy.datatypes.images:Laj"/> diff -r 262b16c8e277 -r f13d85256124 display_applications/ucsc/bam.xml --- a/display_applications/ucsc/bam.xml Thu Mar 11 13:51:53 2010 -0500 +++ b/display_applications/ucsc/bam.xml Thu Mar 11 14:35:36 2010 -0500 @@ -1,8 +1,32 @@ <display id="ucsc_bam" version="1.0.0" name="display at UCSC"> - <link id="main" name="main"> - <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url> - <param type="data" name="bam_file" url="galaxy.bam" strip_https="True" /> - <param type="data" name="bai_file" url="galaxy.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai --> + <!-- Load links from file: one line to one link --> + <dynamic_links from_file="tool-data/shared/ucsc/ucsc_build_sites.txt" skip_startswith="#" id="0" name="0"> + <!-- Define parameters by column from file, allow splitting on builds --> + <dynamic_param name="site_id" value="0"/> + <dynamic_param name="ucsc_link" value="1"/> + <dynamic_param name="builds" value="2" split="True" separator="," /> + <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey --> + <filter>${site_id in $APP.config.ucsc_display_sites}</filter> + <filter>${dataset.dbkey in $builds}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>${ucsc_link}db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url> + <param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" strip_https="True" /> + <param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai --> <param type="template" name="track" viewable="True" strip_https="True">track type=bam name="${bam_file.name}" bigDataUrl=${bam_file.url} db=${bam_file.dbkey}</param> - </link> + </dynamic_links> + <!-- Load links from file: one line to one link --> + <dynamic_links from_file="tool-data/shared/bx/bx_build_sites.txt" skip_startswith="#" id="3" name="3"> + <!-- Define parameters by column from file, allow splitting on builds --> + <dynamic_param name="site_id" value="0"/> + <dynamic_param name="ucsc_link" value="1"/> + <dynamic_param name="builds" value="2" split="True" separator="," /> + <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey --> + <filter>${site_id in $APP.config.bx_display_sites}</filter> + <filter>${dataset.dbkey in $builds}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>${ucsc_link}db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url> + <param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" strip_https="True" /> + <param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai --> + <param type="template" name="track" viewable="True" strip_https="True">track type=bam name="${bam_file.name}" bigDataUrl=${bam_file.url} db=${bam_file.dbkey}</param> + </dynamic_links> </display> diff -r 262b16c8e277 -r f13d85256124 display_applications/ucsc/interval_as_bed.xml --- a/display_applications/ucsc/interval_as_bed.xml Thu Mar 11 13:51:53 2010 -0500 +++ b/display_applications/ucsc/interval_as_bed.xml Thu Mar 11 14:35:36 2010 -0500 @@ -1,7 +1,16 @@ -<display id="ucsc_interval_as_bed" version="1.0.0" name="display at UCSC"> - <link id="main" name="main"> - <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url> - <param type="data" name="bed_file" url="galaxy.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file --> +<display id="ucsc_interval_as_bed" version="1.0.0" name="display at UCSC" inherit="True"> + <!-- Load links from file: one line to one link --> + <dynamic_links from_file="tool-data/shared/ucsc/ucsc_build_sites.txt" skip_startswith="#" id="0" name="0"> + <!-- Define parameters by column from file, allow splitting on builds --> + <dynamic_param name="site_id" value="0"/> + <dynamic_param name="ucsc_link" value="1"/> + <dynamic_param name="builds" value="2" split="True" separator="," /> + <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey --> + <filter>${site_id in $APP.config.ucsc_display_sites}</filter> + <filter>${dataset.dbkey in $builds}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>${ucsc_link}db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url> + <param type="data" name="bed_file" url="galaxy_${DATASET_HASH}.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file --> <param type="template" name="position" strip="True" > #set line_count = 0 #set chrom = None @@ -33,5 +42,49 @@ :- #end if </param> - </link> + </dynamic_links> + <!-- Load links from file: one line to one link --> + <dynamic_links from_file="tool-data/shared/bx/bx_build_sites.txt" skip_startswith="#" id="3" name="3"> + <!-- Define parameters by column from file, allow splitting on builds --> + <dynamic_param name="site_id" value="0"/> + <dynamic_param name="ucsc_link" value="1"/> + <dynamic_param name="builds" value="2" split="True" separator="," /> + <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey --> + <filter>${site_id in $APP.config.bx_display_sites}</filter> + <filter>${dataset.dbkey in $builds}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --> + <url>${ucsc_link}db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url> + <param type="data" name="bed_file" url="galaxy_${DATASET_HASH}.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file --> + <param type="template" name="position" strip="True" > +#set line_count = 0 +#set chrom = None +#set start = float( 'inf' ) +#set end = 0 +#for $line in open( $bed_file.file_name ): + #if $line_count > 10: ##10 max lines to check for view port + #break + #end if + #if not $line.startswith( "#" ): + #set $fields = $line.split( "\t" ) + #try: + #if len( $fields ) >= max( $bed_file.metadata.startCol, $bed_file.metadata.endCol, $bed_file.metadata.chromCol ): + #if $chrom is None or $fields[ $bed_file.metadata.chromCol - 1 ] == $chrom: + #set chrom = $fields[ $bed_file.metadata.chromCol - 1 ] + #set start = min( $start, int( $fields[ $bed_file.metadata.startCol - 1 ] ) ) + #set end = max( $end, int( $fields[ $bed_file.metadata.endCol - 1 ] ) ) + #end if + #end if + #except: + #pass + #end try + #end if + #set line_count += 1 +#end for +#if $chrom is not None: +${chrom}:${start}-${end + 1} +#else: +:- +#end if + </param> + </dynamic_links> </display> diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/data.py --- a/lib/galaxy/datatypes/data.py Thu Mar 11 13:51:53 2010 -0500 +++ b/lib/galaxy/datatypes/data.py Thu Mar 11 14:35:36 2010 -0500 @@ -205,6 +205,15 @@ """New style display applications""" assert display_application.id not in self.display_applications, 'Attempted to add a display application twice' self.display_applications[ display_application.id ] = display_application + def get_display_application( self, key, default = None ): + return self.display_applications.get( key, default ) + def get_display_applications_by_dataset( self, dataset, trans ): + rval = odict() + for key, value in self.display_applications.iteritems(): + value = value.filter_by_dataset( dataset, trans ) + if value.links: + rval[key] = value + return rval def get_display_types(self): """Returns display types available""" return self.supported_display_apps.keys() diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/display_applications/application.py --- a/lib/galaxy/datatypes/display_applications/application.py Thu Mar 11 13:51:53 2010 -0500 +++ b/lib/galaxy/datatypes/display_applications/application.py Thu Mar 11 14:35:36 2010 -0500 @@ -1,24 +1,27 @@ #Contains objects for using external display applications -from galaxy.util import parse_xml +from galaxy.util import parse_xml, string_as_bool from galaxy.util.odict import odict from galaxy.util.template import fill_template from galaxy.web import url_for from parameters import DisplayApplicationParameter, DEFAULT_DATASET_NAME from urllib import quote_plus from util import encode_dataset_user +from copy import deepcopy #Any basic functions that we want to provide as a basic part of parameter dict should be added to this dict BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for } #url_for has route memory... class DisplayApplicationLink( object ): @classmethod - def from_elem( cls, elem, display_application ): + def from_elem( cls, elem, display_application, other_values = None ): rval = DisplayApplicationLink( display_application ) rval.id = elem.get( 'id', None ) assert rval.id, 'Link elements require a id.' rval.name = elem.get( 'name', rval.id ) rval.url = elem.find( 'url' ) assert rval.url is not None, 'A url element must be provided for link elements.' + rval.other_values = other_values + rval.filters = elem.findall( 'filter' ) for param_elem in elem.findall( 'param' ): param = DisplayApplicationParameter.from_elem( param_elem, rval ) assert param, 'Unable to load parameter from element: %s' % param_elem @@ -36,13 +39,19 @@ dataset_hash, user_hash = encode_dataset_user( trans, data, None ) return url_for( controller = '/dataset', action = "display_application", dataset_id = dataset_hash, user_id = user_hash, app_name = self.display_application.id, link_name = self.id, app_action = None ) def get_inital_values( self, data, trans ): - rval = odict( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here + if self.other_values: + rval = odict( self.other_values ) + else: + rval = odict() + rval.update( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here for key, value in BASE_PARAMS.iteritems(): #add helper functions/variables rval[ key ] = value rval[ DEFAULT_DATASET_NAME ] = data #always have the display dataset name available return rval def build_parameter_dict( self, data, dataset_hash, user_hash, trans ): other_values = self.get_inital_values( data, trans ) + other_values[ 'DATASET_HASH' ] = dataset_hash + other_values[ 'USER_HASH' ] = user_hash for name, param in self.parameters.iteritems(): assert name not in other_values, "The display parameter '%s' has been defined more than once." % name if param.ready( other_values ): @@ -51,6 +60,51 @@ other_values[ name ] = None return False, other_values #need to stop here, next params may need this value return True, other_values #we built other_values, lets provide it as well, or else we will likely regenerate it in the next step + def filter_by_dataset( self, data, trans ): + context = self.get_inital_values( data, trans ) + for filter_elem in self.filters: + if fill_template( filter_elem.text, context = context ) != filter_elem.get( 'value', 'True' ): + return False + return True + +class DynamicDisplayApplicationBuilder( object ): + @classmethod + def __init__( self, elem, display_application ): + rval = [] + filename = elem.get( 'from_file', None ) + assert filename is not None, 'Filename and id attributes required for dynamic_links' + skip_startswith = elem.get( 'skip_startswith', None ) + separator = elem.get( 'separator', '\t' ) + id_col = int( elem.get( 'id', None ) ) + name_col = int( elem.get( 'name', id_col ) ) + dynamic_params = {} + max_col = max( id_col, name_col ) + for dynamic_param in elem.findall( 'dynamic_param' ): + name = dynamic_param.get( 'name' ) + value = int( dynamic_param.get( 'value' ) ) + split = string_as_bool( dynamic_param.get( 'split', False ) ) + param_separator = dynamic_param.get( 'separator', ',' ) + max_col = max( max_col, value ) + dynamic_params[name] = { 'column': value, 'split': split, 'separator': param_separator } + for line in open( filename ): + if not skip_startswith or not line.startswith( skip_startswith ): + line = line.rstrip( '\n\r' ) + fields = line.split( separator ) + if len( fields ) >= max_col: + new_elem = deepcopy( elem ) + new_elem.set( 'id', fields[id_col] ) + new_elem.set( 'name', fields[name_col] ) + dynamic_values = {} + for key, attributes in dynamic_params.iteritems(): + value = fields[ attributes[ 'column' ] ] + if attributes['split']: + value = value.split( attributes['separator'] ) + dynamic_values[key] = value + #now populate + rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) ) + self.links = rval + def __iter__( self ): + return iter( self.links ) class PopulatedDisplayApplicationLink( object ): def __init__( self, display_application_link, data, dataset_hash, user_hash, trans ): @@ -84,9 +138,11 @@ def display_url( self ): assert self.display_ready(), 'Display is not yet ready, cannot generate display link' return fill_template( self.link.url.text, context = self.parameters ) - def get_param_name_by_url( self, name ): - assert name in self.link.url_param_name_map, "Unknown URL parameter name provided: %s" % name - return self.link.url_param_name_map[ name ] + def get_param_name_by_url( self, url ): + for name, parameter in self.link.parameters.iteritems(): + if parameter.build_url( self.parameters ) == url: + return name + raise ValueError( "Unknown URL parameter name provided: %s" % url ) class DisplayApplication( object ): @classmethod @@ -103,6 +159,9 @@ link = DisplayApplicationLink.from_elem( link_elem, rval ) if link: rval.links[ link.id ] = link + for dynamic_links in elem.findall( 'dynamic_links' ): + for link in DynamicDisplayApplicationBuilder( dynamic_links, rval ): + rval.links[ link.id ] = link return rval def __init__( self, display_id, name, datatypes_registry, version = None ): self.id = display_id @@ -115,4 +174,9 @@ def get_link( self, link_name, data, dataset_hash, user_hash, trans ): #returns a link object with data knowledge to generate links return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans ) - + def filter_by_dataset( self, data, trans ): + filtered = DisplayApplication( self.id, self.name, self.datatypes_registry, version = self.version ) + for link_name, link_value in self.links.iteritems(): + if link_value.filter_by_dataset( data, trans ): + filtered.links[link_name] = link_value + return filtered diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/display_applications/parameters.py --- a/lib/galaxy/datatypes/display_applications/parameters.py Thu Mar 11 13:51:53 2010 -0500 +++ b/lib/galaxy/datatypes/display_applications/parameters.py Thu Mar 11 14:35:36 2010 -0500 @@ -35,6 +35,8 @@ return True def is_preparing( self, other_values ): return False + def build_url( self, other_values ): + return fill_template( self.url, context = other_values ) class DisplayApplicationDataParameter( DisplayApplicationParameter ): """ Parameter that returns a file_name containing the requested content """ @@ -141,15 +143,16 @@ self.trans = trans self._dataset_hash = dataset_hash self._user_hash = user_hash + self._url = self.parameter.build_url( self.other_values ) def __str__( self ): return str( self.value ) def mime_type( self ): if self.parameter.mime_type is not None: return self.parameter.mime_type if self.parameter.guess_mime_type: - mime, encoding = mimetypes.guess_type( self.parameter.url ) + mime, encoding = mimetypes.guess_type( self._url ) if not mime: - mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None ) + mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self._url )[ -1 ], None ) if mime: return mime return 'text/plain' @@ -158,7 +161,7 @@ base_url = self.trans.request.base if self.parameter.strip_https and base_url[ : 5].lower() == 'https': base_url = "http%s" % base_url[ 5: ] - return "%s%s" % ( base_url, url_for( controller = '/dataset', action = "display_application", dataset_id = self._dataset_hash, user_id = self._user_hash, app_name = self.parameter.link.display_application.id, link_name = self.parameter.link.id, app_action = self.action_name, action_param = self.parameter.url ) ) + return "%s%s" % ( base_url, url_for( controller = '/dataset', action = "display_application", dataset_id = self._dataset_hash, user_id = self._user_hash, app_name = self.parameter.link.display_application.id, link_name = self.parameter.link.id, app_action = self.action_name, action_param = self._url ) ) @property def action_name( self ): return self.ACTION_NAME @@ -178,9 +181,9 @@ if self.parameter.mime_type is not None: return self.parameter.mime_type if self.parameter.guess_mime_type: - mime, encoding = mimetypes.guess_type( self.parameter.url ) + mime, encoding = mimetypes.guess_type( self._url ) if not mime: - mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None ) + mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self._url )[ -1 ], None ) if mime: return mime return self.other_values[ DEFAULT_DATASET_NAME ].get_mime() diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/registry.py --- a/lib/galaxy/datatypes/registry.py Thu Mar 11 13:51:53 2010 -0500 +++ b/lib/galaxy/datatypes/registry.py Thu Mar 11 14:35:36 2010 -0500 @@ -25,6 +25,7 @@ self.sniff_order = [] self.upload_file_formats = [] self.display_applications = odict() #map a display application id to a display application + inherit_display_application_by_class = [] if root_dir and config: # Parse datatypes_conf.xml tree = galaxy.util.parse_xml( config ) @@ -42,11 +43,11 @@ for elem in registration.findall( 'datatype' ): try: extension = elem.get( 'extension', None ) - type = elem.get( 'type', None ) + dtype = elem.get( 'type', None ) mimetype = elem.get( 'mimetype', None ) display_in_upload = elem.get( 'display_in_upload', False ) - if extension and type: - fields = type.split( ':' ) + if extension and dtype: + fields = dtype.split( ':' ) datatype_module = fields[0] datatype_class = fields[1] fields = datatype_module.split( '.' ) @@ -85,27 +86,36 @@ for display_app in elem.findall( 'display' ): display_file = display_app.get( 'file', None ) assert display_file is not None, "A file must be specified for a datatype display tag." + inherit = galaxy.util.string_as_bool( display_app.get( 'inherit', 'False' ) ) display_app = DisplayApplication.from_file( os.path.join( self.display_applications_path, display_file ), self ) if display_app: if display_app.id in self.display_applications: #if we already loaded this display application, we'll use the first one again display_app = self.display_applications[ display_app.id ] - self.log.debug( "Loaded display application '%s' for datatype '%s'" % ( display_app.id, extension ) ) + self.log.debug( "Loaded display application '%s' for datatype '%s', inherit=%s" % ( display_app.id, extension, inherit ) ) self.display_applications[ display_app.id ] = display_app #Display app by id self.datatypes_by_extension[ extension ].add_display_application( display_app ) - + if inherit and ( self.datatypes_by_extension[extension], display_app ) not in inherit_display_application_by_class: + #subclass inheritance will need to wait until all datatypes have been loaded + inherit_display_application_by_class.append( ( self.datatypes_by_extension[extension], display_app ) ) except Exception, e: self.log.warning( 'Error loading datatype "%s", problem: %s' % ( extension, str( e ) ) ) + # Handle display_application subclass inheritance here: + for ext, d_type1 in self.datatypes_by_extension.iteritems(): + for d_type2, display_app in inherit_display_application_by_class: + current_app = d_type1.get_display_application( display_app.id, None ) + if current_app is None and isinstance( d_type1, type( d_type2 ) ): + d_type1.add_display_application( display_app ) # Load datatype sniffers from the config sniff_order = [] sniffers = root.find( 'sniffers' ) for elem in sniffers.findall( 'sniffer' ): - type = elem.get( 'type', None ) - if type: - sniff_order.append( type ) - for type in sniff_order: + dtype = elem.get( 'type', None ) + if dtype: + sniff_order.append( dtype ) + for dtype in sniff_order: try: - fields = type.split( ":" ) + fields = dtype.split( ":" ) datatype_module = fields[0] datatype_class = fields[1] fields = datatype_module.split( "." ) @@ -120,9 +130,9 @@ break if not included: self.sniff_order.append( aclass ) - self.log.debug( 'Loaded sniffer for datatype: %s' % type ) + self.log.debug( 'Loaded sniffer for datatype: %s' % dtype ) except Exception, exc: - self.log.warning( 'Error appending datatype %s to sniff_order, problem: %s' % ( type, str( exc ) ) ) + self.log.warning( 'Error appending datatype %s to sniff_order, problem: %s' % ( dtype, str( exc ) ) ) #default values if len(self.datatypes_by_extension) < 1: self.datatypes_by_extension = { diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py Thu Mar 11 13:51:53 2010 -0500 +++ b/lib/galaxy/model/__init__.py Thu Mar 11 14:35:36 2010 -0500 @@ -637,6 +637,9 @@ return ( None, None ) return get_source( self ) + def get_display_applications( self, trans ): + return self.datatype.get_display_applications_by_dataset( self, trans ) + class HistoryDatasetAssociation( DatasetInstance ): def __init__( self, hid = None, diff -r 262b16c8e277 -r f13d85256124 templates/root/history_common.mako --- a/templates/root/history_common.mako Thu Mar 11 13:51:53 2010 -0500 +++ b/templates/root/history_common.mako Thu Mar 11 14:35:36 2010 -0500 @@ -102,7 +102,7 @@ %endif %endfor %endif - %for display_app in data.datatype.display_applications.itervalues(): + %for display_app in data.get_display_applications( trans ).itervalues(): | ${display_app.name} %for link_app in display_app.links.itervalues(): <a target="${link_app.url.get( 'target_frame', '_blank' )}" href="${link_app.get_display_url( data, trans )}">${_(link_app.name)}</a> diff -r 262b16c8e277 -r f13d85256124 tool-data/shared/bx/bx_build_sites.txt --- a/tool-data/shared/bx/bx_build_sites.txt Thu Mar 11 13:51:53 2010 -0500 +++ b/tool-data/shared/bx/bx_build_sites.txt Thu Mar 11 14:35:36 2010 -0500 @@ -1,1 +1,1 @@ -main http://main.genome-browser.bx.psu.edu/cgi-bin/hgTracks? hg18,hg19,mm8,mm9 +main http://main.genome-browser.bx.psu.edu/cgi-bin/hgTracks? hg18,hg19,mm8,mm9 bx-main