galaxy-commits
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: dan: Always load the tool version with the highest lineage into the tool panel.
by Bitbucket 27 Sep '12
by Bitbucket 27 Sep '12
27 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/14c1b3e05fb8/
changeset: 14c1b3e05fb8
user: dan
date: 2012-09-27 18:40:05
summary: Always load the tool version with the highest lineage into the tool panel.
affected #: 1 file
diff -r 0527905739fe10789de3d331a44dec3507bdfdb2 -r 14c1b3e05fb884ba7b6f46a0ba3adb91bcae6485 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -159,6 +159,8 @@
else:
panel_dict = panel_component
already_loaded = False
+ loaded_version_key = None
+ lineage_id = None
for lineage_id in tool.lineage_ids:
if lineage_id in self.tools_by_id:
loaded_version_key = 'tool_%s' % lineage_id
@@ -176,7 +178,13 @@
if not inserted:
# If the tool is not defined in integrated_tool_panel.xml, append it to the tool panel.
panel_dict[ key ] = tool
- log.debug( "Loaded tool id: %s, version: %s." % ( tool.id, tool.version ) )
+ log.debug( "Loaded tool id: %s, version: %s into tool panel." % ( tool.id, tool.version ) )
+ elif tool.lineage_ids.index( tool_id ) > tool.lineage_ids.index( lineage_id ):
+ key = 'tool_%s' % tool.id
+ index = panel_dict.keys().index( loaded_version_key )
+ del panel_dict[ loaded_version_key ]
+ panel_dict.insert( index, key, tool )
+ log.debug( "Loaded tool id: %s, version: %s into tool panel." % ( tool.id, tool.version ) )
def load_tool_panel( self ):
for key, val in self.integrated_tool_panel.items():
if key.startswith( 'tool_' ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/371f6770d25c/
changeset: 371f6770d25c
user: dan
date: 2012-09-27 17:46:12
summary: Refactor toolbox.get_tool. Store 'original tool.id' as tool.old_id.
affected #: 1 file
diff -r c28c5f906c6bdbbe799cfcc559760f26029090ce -r 371f6770d25cc5942fad87e8f43e8ce736c75838 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -291,34 +291,33 @@
os.chmod( self.integrated_tool_panel_config, 0644 )
def get_tool( self, tool_id, tool_version=None, get_all_versions=False ):
"""Attempt to locate a tool in the tool box."""
- if tool_id in self.tools_by_id:
- tool = self.tools_by_id[ tool_id ]
- if tool_version and tool.version == tool_version:
- if get_all_versions:
- return [ tool ]
- else:
- return tool
- else:
- if get_all_versions:
- return [ tool ]
- else:
- return tool
+ if tool_id in self.tools_by_id and not get_all_versions:
+ #tool_id exactly matches an available tool by id (which is 'old' tool_id or guid)
+ return self.tools_by_id[ tool_id ]
+ #exact tool id match not found, or all versions requested, search for other options, e.g. migrated tools or different versions
+ rval = []
tv = self.__get_tool_version( tool_id )
if tv:
tool_version_ids = tv.get_version_ids( self.app )
- if get_all_versions:
- available_tool_versions = []
- for tool_version_id in tool_version_ids:
- if tool_version_id in self.tools_by_id:
- available_tool_versions.append( self.tools_by_id[ tool_version_id ] )
- return available_tool_versions
for tool_version_id in tool_version_ids:
if tool_version_id in self.tools_by_id:
- tool = self.tools_by_id[ tool_version_id ]
- if tool_version and tool.version == tool_version:
- return tool
- else:
- return tool
+ rval.append( self.tools_by_id[ tool_version_id ] )
+ if not rval:
+ #still no tool, do a deeper search and try to match by old ids
+ for tool in self.tools_by_id.itervalues():
+ if tool.old_id == tool_id:
+ rval.append( tool )
+ if rval:
+ if get_all_versions:
+ return rval
+ else:
+ if tool_version:
+ #return first tool with matching version
+ for tool in rval:
+ if tool.version == tool_version:
+ return tool
+ #No tool matches by version, simply return the first available tool found
+ return rval[0]
return None
def get_loaded_tools_by_lineage( self, tool_id ):
"""Get all loaded tools associated by lineage to the tool whose id is tool_id."""
@@ -381,7 +380,6 @@
tool.repository_owner = repository_owner
tool.installed_changeset_revision = installed_changeset_revision
tool.guid = guid
- tool.old_id = elem.find( "id" ).text
tool.version = elem.find( "version" ).text
# Make sure the tool has a tool_version.
if not self.__get_tool_version( tool.id ):
@@ -906,8 +904,9 @@
if not self.name:
raise Exception, "Missing tool 'name'"
# Get the UNIQUE id for the tool
+ self.old_id = root.get( "id" )
if guid is None:
- self.id = root.get( "id" )
+ self.id = self.old_id
else:
self.id = guid
if not self.id:
https://bitbucket.org/galaxy/galaxy-central/changeset/5adfb582cca4/
changeset: 5adfb582cca4
user: dan
date: 2012-09-27 17:46:12
summary: Refactor tool selection during rerun. Always allow selecting different versions of a tool when first accessed in tool_runner.
affected #: 1 file
diff -r 371f6770d25cc5942fad87e8f43e8ce736c75838 -r 5adfb582cca4305295f88d6128ccaa54c72a8977 lib/galaxy/web/controllers/tool_runner.py
--- a/lib/galaxy/web/controllers/tool_runner.py
+++ b/lib/galaxy/web/controllers/tool_runner.py
@@ -50,27 +50,21 @@
tools = toolbox.get_loaded_tools_by_lineage( tool_id )
else:
tools = toolbox.get_tool( tool_id, tool_version=tool_version, get_all_versions=True )
- if len( tools ) > 1:
- tool_version_select_field = self.build_tool_version_select_field( tools, tool_id, set_selected )
- for tool in tools:
- if tool.id == tool_id:
- break
- else:
- tool = tools[ 0 ]
- else:
- tool = tools[ 0 ]
- break
+ if tools:
+ tool = toolbox.get_tool( tool_id, tool_version=tool_version, get_all_versions=False )
+ if len( tools ) > 1:
+ tool_version_select_field = self.build_tool_version_select_field( tools, tool.id, set_selected )
+ break
return tool_version_select_field, tools, tool
@web.expose
def index(self, trans, tool_id=None, from_noframe=None, **kwd):
# No tool id passed, redirect to main page
if tool_id is None:
return trans.response.send_redirect( url_for( "/static/welcome.html" ) )
- set_selected = 'refresh' in kwd
tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
tool_version=None,
- get_loaded_tools_by_lineage=True,
- set_selected=set_selected )
+ get_loaded_tools_by_lineage=False,
+ set_selected=True )
# No tool matching the tool id, display an error (shouldn't happen)
if not tool:
log.error( "index called with tool id '%s' but no such tool exists", tool_id )
https://bitbucket.org/galaxy/galaxy-central/changeset/c76e2882d2d2/
changeset: c76e2882d2d2
user: dan
date: 2012-09-27 17:46:13
summary: Better handling of determining tool/version in workflow tool module.
affected #: 1 file
diff -r 5adfb582cca4305295f88d6128ccaa54c72a8977 -r c76e2882d2d23be86cb914df619af4b3e33911cf lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -199,13 +199,9 @@
# TODO: If workflows are ever enhanced to use tool version
# in addition to tool id, enhance the selection process here
# to retrieve the correct version of the tool.
- tool_version = Class.__get_tool_version( trans, tool_id )
- if tool_version:
- tool_version_ids = tool_version.get_version_ids( trans.app )
- for tool_version_id in tool_version_ids:
- if tool_version_id in trans.app.toolbox.tools_by_id:
- tool_id = tool_version_id
- break
+ tool = trans.app.toolbox.get_tool( tool_id )
+ if tool:
+ tool_id = tool.id
if ( trans.app.toolbox and tool_id in trans.app.toolbox.tools_by_id ):
module = Class( trans, tool_id )
module.state = DefaultToolState()
https://bitbucket.org/galaxy/galaxy-central/changeset/e6289956e267/
changeset: e6289956e267
user: dan
date: 2012-09-27 17:46:13
summary: Display tool version in workflow tool form editor.
affected #: 1 file
diff -r c76e2882d2d23be86cb914df619af4b3e33911cf -r e6289956e267c5e98b343b8ae1149b8af89a26e6 templates/workflow/editor_tool_form.mako
--- a/templates/workflow/editor_tool_form.mako
+++ b/templates/workflow/editor_tool_form.mako
@@ -98,6 +98,9 @@
<div class="toolForm"><div class="toolFormTitle">Tool: ${tool.name}</div>
+ %if tool.version:
+ <div class="form-row"><div class='titleRow'>Version: ${tool.version}</div></div>
+ %endif
<div class="toolFormBody"><input type="hidden" name="tool_id" value="${tool.id}" />
%for i, inputs in enumerate( tool.inputs_by_page ):
https://bitbucket.org/galaxy/galaxy-central/changeset/0527905739fe/
changeset: 0527905739fe
user: dan
date: 2012-09-27 17:46:13
summary: Display tool version when running a workflow.
affected #: 1 file
diff -r e6289956e267c5e98b343b8ae1149b8af89a26e6 -r 0527905739fe10789de3d331a44dec3507bdfdb2 templates/workflow/run.mako
--- a/templates/workflow/run.mako
+++ b/templates/workflow/run.mako
@@ -379,6 +379,9 @@
<div class="toolForm"><div class="toolFormTitle"><span class='title_ul_text'>Step ${int(step.order_index)+1}: ${tool.name}</span>
+ %if tool.version:
+ (version ${tool.version})
+ %endif
% if step.annotations:
<div class="step-annotation">${h.to_unicode( step.annotations[0].annotation )}</div>
% endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add the ability to view a tool shed repository's README file from the pop-up menu on pages in the tool shed repository as well as in Galaxy for the installed repository.
by Bitbucket 27 Sep '12
by Bitbucket 27 Sep '12
27 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/c28c5f906c6b/
changeset: c28c5f906c6b
user: greg
date: 2012-09-27 16:33:55
summary: Add the ability to view a tool shed repository's README file from the pop-up menu on pages in the tool shed repository as well as in Galaxy for the installed repository.
affected #: 28 files
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/tool_shed/install_manager.py
--- a/lib/galaxy/tool_shed/install_manager.py
+++ b/lib/galaxy/tool_shed/install_manager.py
@@ -133,6 +133,7 @@
for k, v in tool_panel_dict_for_tool_config.items():
tool_panel_dict_for_display[ k ] = v
metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=self.app,
+ repository=tool_shed_repository,
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
repository_files_dir=None,
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -31,8 +31,8 @@
'&' : '&',
'\'' : ''' }
MAX_CONTENT_SIZE = 32768
+NOT_TOOL_CONFIGS = [ 'datatypes_conf.xml', 'tool_dependencies.xml' ]
VALID_CHARS = set( string.letters + string.digits + "'\"-=_.()/+*^,:?!#[]%\\$@;{}" )
-NOT_TOOL_CONFIGS = [ 'datatypes_conf.xml', 'tool_dependencies.xml' ]
class ShedCounter( object ):
def __init__( self, model ):
@@ -602,7 +602,7 @@
else:
tool_dependencies_dict[ 'set_environment' ] = [ requirements_dict ]
return tool_dependencies_dict
-def generate_metadata_for_changeset_revision( app, repository_clone_url, relative_install_dir=None, repository_files_dir=None,
+def generate_metadata_for_changeset_revision( app, repository, repository_clone_url, relative_install_dir=None, repository_files_dir=None,
resetting_all_metadata_on_repository=False, webapp='galaxy' ):
"""
Generate metadata for a repository using it's files on disk. To generate metadata for changeset revisions older than the repository tip,
@@ -610,6 +610,7 @@
disk files, so the value of repository_files_dir will not always be repository.repo_path (it could be an absolute path to a temporary directory
containing a clone). If it is an absolute path, the value of relative_install_dir must contain repository.repo_path.
"""
+ readme_file_names = get_readme_file_names( repository.name )
metadata_dict = {}
invalid_file_tups = []
invalid_tool_configs = []
@@ -653,14 +654,24 @@
tool_data_path=app.config.tool_data_path,
tool_data_table_config_path=app.config.tool_data_table_config_path,
persist=False )
- # Find all tool configs and exported workflows and add them to the repository's metadata.
for root, dirs, files in os.walk( files_dir ):
if root.find( '.hg' ) < 0 and root.find( 'hgrc' ) < 0:
if '.hg' in dirs:
dirs.remove( '.hg' )
for name in files:
- # Find all tool configs.
- if name not in NOT_TOOL_CONFIGS and name.endswith( '.xml' ):
+ # See if we have a READ_ME file.
+ if name.lower() in readme_file_names:
+ if resetting_all_metadata_on_repository:
+ full_path_to_readme = os.path.join( root, name )
+ stripped_path_to_readme = full_path_to_readme.replace( work_dir, '' )
+ if stripped_path_to_readme.startswith( '/' ):
+ stripped_path_to_readme = stripped_path_to_readme[ 1: ]
+ relative_path_to_readme = os.path.join( relative_install_dir, stripped_path_to_readme )
+ else:
+ relative_path_to_readme = os.path.join( root, name )
+ metadata_dict[ 'readme' ] = relative_path_to_readme
+ # See if we have a tool config.
+ elif name not in NOT_TOOL_CONFIGS and name.endswith( '.xml' ):
full_path = os.path.abspath( os.path.join( root, name ) )
if os.path.getsize( full_path ) > 0:
if not ( check_binary( full_path ) or check_image( full_path ) or check_gzip( full_path )[ 0 ]
@@ -699,7 +710,7 @@
else:
for tup in invalid_files_and_errors_tups:
invalid_file_tups.append( tup )
- # Find all exported workflows
+ # Find all exported workflows.
elif name.endswith( '.ga' ):
relative_path = os.path.join( root, name )
if os.path.getsize( os.path.abspath( relative_path ) ) > 0:
@@ -1195,6 +1206,25 @@
if contents:
contents.sort()
return contents
+def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ):
+ """Get metadata for a specified repository change set from the database"""
+ # Make sure there are no duplicate records, and return the single unique record for the changeset_revision. Duplicate records were somehow
+ # created in the past. The cause of this issue has been resolved, but we'll leave this method as is for a while longer to ensure all duplicate
+ # records are removed.
+ all_metadata_records = trans.sa_session.query( trans.model.RepositoryMetadata ) \
+ .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ),
+ trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \
+ .order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \
+ .all()
+ if len( all_metadata_records ) > 1:
+ # Delete all recrds older than the last one updated.
+ for repository_metadata in all_metadata_records[ 1: ]:
+ trans.sa_session.delete( repository_metadata )
+ trans.sa_session.flush()
+ return all_metadata_records[ 0 ]
+ elif all_metadata_records:
+ return all_metadata_records[ 0 ]
+ return None
def get_repository_owner( cleaned_repository_url ):
items = cleaned_repository_url.split( 'repos' )
repo_path = items[ 1 ]
@@ -1405,6 +1435,13 @@
return shed_url
# The tool shed from which the repository was originally installed must no longer be configured in tool_sheds_conf.xml.
return None
+def get_readme_file_names( repository_name ):
+ readme_files = [ 'readme', 'read_me', 'install' ]
+ valid_filenames = [ r for r in readme_files ]
+ for r in readme_files:
+ valid_filenames.append( '%s.txt' % r )
+ valid_filenames.append( '%s.txt' % repository_name )
+ return valid_filenames
def handle_missing_data_table_entry( app, relative_install_dir, tool_path, repository_tools_tups ):
"""
Inspect each tool to see if any have input parameters that are dynamically generated select lists that require entries in the
@@ -1907,6 +1944,19 @@
elif c not in [ '\r' ]:
translated.append( '' )
return ''.join( translated )
+def translate_string( raw_text, to_html=True ):
+ if raw_text:
+ if to_html:
+ if len( raw_text ) <= MAX_CONTENT_SIZE:
+ translated_string = to_html_str( raw_text )
+ else:
+ large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE )
+ translated_string = to_html_str( '%s%s' % ( raw_text[ 0:MAX_CONTENT_SIZE ], large_str ) )
+ else:
+ raise Exception( "String translation currently only supports text to HTML." )
+ else:
+ translated_string = ''
+ return translated_string
def update_repository( repo, ctx_rev=None ):
"""
Update the cloned repository to changeset_revision. It is critical that the installed repository is updated to the desired
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/web/controllers/admin_toolshed.py
--- a/lib/galaxy/web/controllers/admin_toolshed.py
+++ b/lib/galaxy/web/controllers/admin_toolshed.py
@@ -342,8 +342,10 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
repository = get_repository( trans, kwd[ 'id' ] )
+ has_readme = repository.metadata and 'readme' in repository.metadata
return trans.fill_template( '/admin/tool_shed_repository/browse_repository.mako',
repository=repository,
+ has_readme=has_readme,
message=message,
status=status )
@web.expose
@@ -388,8 +390,11 @@
message += "Choose <b>Uninstall this tool dependency</b> from the <b>Repository Actions</b> menu, correct problems "
message += "if necessary, and try installing the dependency again."
status = "error"
+ tool_shed_repository = tool_dependency.tool_shed_repository
+ has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata
return trans.fill_template( '/admin/tool_shed_repository/browse_tool_dependency.mako',
- repository=tool_dependency.tool_shed_repository,
+ repository=tool_shed_repository,
+ has_readme=has_readme,
tool_dependency=tool_dependency,
in_error_state=in_error_state,
can_uninstall=can_uninstall,
@@ -487,9 +492,11 @@
message=message,
status=status ) )
remove_from_disk_check_box = CheckboxField( 'remove_from_disk', checked=remove_from_disk_checked )
+ has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata
return trans.fill_template( '/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako',
repository=tool_shed_repository,
remove_from_disk_check_box=remove_from_disk_check_box,
+ has_readme=has_readme,
message=message,
status=status )
@web.expose
@@ -716,6 +723,7 @@
when an admin is installing a new repository or reinstalling an uninstalled repository.
"""
metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app,
+ repository=tool_shed_repository,
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
repository_files_dir=None,
@@ -837,8 +845,10 @@
trans.sa_session.add( repository )
trans.sa_session.flush()
message = "Repository metadata has been reset."
+ has_readme = repository.metadata and 'readme' in repository.metadata
return trans.fill_template( '/admin/tool_shed_repository/manage_repository.mako',
repository=repository,
+ has_readme=has_readme,
in_error_state=in_error_state,
can_install=can_install,
description=description,
@@ -914,14 +924,14 @@
tool_shed_repository = tool_dependency.tool_shed_repository
self.tool_dependency_grid.title = "Tool shed repository '%s' tool dependencies" % tool_shed_repository.name
self.tool_dependency_grid.global_actions = \
- [ grids.GridAction( label='Browse repository',
+ [ grids.GridAction( label='Manage repository',
+ url_args=dict( controller='admin_toolshed',
+ action='manage_repository',
+ id=trans.security.encode_id( tool_shed_repository.id ) ) ),
+ grids.GridAction( label='Browse repository',
url_args=dict( controller='admin_toolshed',
action='browse_repository',
id=trans.security.encode_id( tool_shed_repository.id ) ) ),
- grids.GridAction( label='Manage repository',
- url_args=dict( controller='admin_toolshed',
- action='manage_repository',
- id=trans.security.encode_id( tool_shed_repository.id ) ) ),
grids.GridAction( label='Get repository updates',
url_args=dict( controller='admin_toolshed',
action='check_for_updates',
@@ -934,6 +944,12 @@
url_args=dict( controller='admin_toolshed',
action='deactivate_or_uninstall_repository',
id=trans.security.encode_id( tool_shed_repository.id ) ) ) ]
+ if tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata:
+ view_readme_action = grids.GridAction( label='View README',
+ url_args=dict( controller='admin_toolshed',
+ action='view_readme',
+ id=trans.security.encode_id( tool_shed_repository.id ) ) )
+ self.tool_dependency_grid.global_actions.insert( 1, view_readme_action )
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
if not tool_dependency_ids:
@@ -1181,13 +1197,7 @@
response = urllib2.urlopen( url )
raw_text = response.read()
response.close()
- readme_text = ''
- for i, line in enumerate( raw_text ):
- readme_text = '%s%s' % ( readme_text, to_html_str( line ) )
- if len( readme_text ) > MAX_CONTENT_SIZE:
- large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE )
- readme_text = '%s%s' % ( readme_text, to_html_str( large_str ) )
- break
+ readme_text = translate_string( raw_text, to_html=True )
else:
readme_text = ''
if trans.app.config.tool_dependency_dir is None:
@@ -1418,8 +1428,19 @@
status = 'warning'
includes_tool_dependencies = 'tool_dependencies' in metadata
install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=True )
+ if metadata and 'readme' in metadata:
+ url = url_join( tool_shed_url,
+ 'repository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy' % \
+ ( repository.name, repository.owner, repository.installed_changeset_revision ) )
+ response = urllib2.urlopen( url )
+ raw_text = response.read()
+ response.close()
+ readme_text = translate_string( raw_text, to_html=True )
+ else:
+ readme_text = ''
return trans.fill_template( '/admin/tool_shed_repository/reselect_tool_panel_section.mako',
repository=repository,
+ readme_text=readme_text,
no_changes_check_box=no_changes_check_box,
original_section_name=original_section_name,
install_tool_dependencies_check_box=install_tool_dependencies_check_box,
@@ -1527,6 +1548,8 @@
for tool_dependency_id in tool_dependency_ids:
tool_dependency = get_tool_dependency( trans, tool_dependency_id )
tool_dependencies.append( tool_dependency )
+ tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
+ has_readme = tool_shed_repository.metadata and 'readme' in tool_shed_repository.metadata
if kwd.get( 'uninstall_tool_dependencies_button', False ):
errors = False
# Filter tool dependencies to only those that are installed.
@@ -1545,7 +1568,6 @@
status = 'error'
else:
message = "These tool dependencies have been uninstalled: %s" % ','.join( td.name for td in tool_dependencies_for_uninstallation )
- tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
td_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='manage_tool_dependencies',
@@ -1553,6 +1575,9 @@
status=status,
message=message ) )
return trans.fill_template( '/admin/tool_shed_repository/uninstall_tool_dependencies.mako',
+ repository=tool_shed_repository,
+ has_readme=has_readme,
+ tool_dependency_ids=tool_dependency_ids,
tool_dependencies=tool_dependencies,
message=message,
status=status )
@@ -1616,27 +1641,55 @@
status=status ) )
@web.expose
@web.require_admin
+ def view_readme( self, trans, id, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ cntrller = params.get( 'cntrller', 'admin_toolshed' )
+ status = params.get( 'status', 'done' )
+ repository = get_repository( trans, id )
+ metadata = repository.metadata
+ if metadata and 'readme' in metadata:
+ f = open( metadata[ 'readme' ], 'r' )
+ raw_text = f.read()
+ f.close()
+ readme_text = translate_string( raw_text, to_html=True )
+ else:
+ readme_text = ''
+ is_malicious = False
+ return trans.fill_template( '/webapps/community/common/view_readme.mako',
+ cntrller=cntrller,
+ repository=repository,
+ changeset_revision=repository.changeset_revision,
+ readme_text=readme_text,
+ is_malicious=is_malicious,
+ webapp='galaxy',
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_admin
def view_tool_metadata( self, trans, repository_id, tool_id, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
webapp = get_webapp( trans, **kwd )
repository = get_repository( trans, repository_id )
- metadata = {}
+ repository_metadata = repository.metadata
+ tool_metadata = {}
tool_lineage = []
tool = None
- if 'tools' in repository.metadata:
- for tool_metadata_dict in repository.metadata[ 'tools' ]:
+ if 'tools' in repository_metadata:
+ for tool_metadata_dict in repository_metadata[ 'tools' ]:
if tool_metadata_dict[ 'id' ] == tool_id:
- metadata = tool_metadata_dict
- tool = trans.app.toolbox.load_tool( os.path.abspath( metadata[ 'tool_config' ] ), guid=metadata[ 'guid' ] )
+ tool_metadata = tool_metadata_dict
+ tool = trans.app.toolbox.load_tool( os.path.abspath( tool_metadata[ 'tool_config' ] ), guid=metadata[ 'guid' ] )
if tool:
tool_lineage = self.get_versions_of_tool( trans.app, tool.id )
break
return trans.fill_template( "/admin/tool_shed_repository/view_tool_metadata.mako",
repository=repository,
+ repository_metadata=repository_metadata,
tool=tool,
- metadata=metadata,
+ tool_metadata=tool_metadata,
tool_lineage=tool_lineage,
message=message,
status=status )
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -7,9 +7,9 @@
from galaxy.util.hash_util import *
from galaxy.util.shed_util import check_tool_input_params, clone_repository, concat_messages, copy_sample_file, generate_metadata_for_changeset_revision
from galaxy.util.shed_util import get_changectx_for_changeset, get_config_from_disk, get_configured_ui, get_file_context_from_ctx, get_named_tmpfile_from_ctx
-from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_disk, handle_sample_files_and_load_tool_from_tmp_config
-from galaxy.util.shed_util import handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH, load_tool_from_config, reset_tool_data_tables
-from galaxy.util.shed_util import reversed_upper_bounded_changelog, strip_path
+from galaxy.util.shed_util import get_repository_metadata_by_changeset_revision, handle_sample_files_and_load_tool_from_disk
+from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_tmp_config, handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH
+from galaxy.util.shed_util import load_tool_from_config, reset_tool_data_tables, reversed_upper_bounded_changelog, strip_path
from galaxy.web.base.controller import *
from galaxy.webapps.community import model
from galaxy.model.orm import *
@@ -473,25 +473,6 @@
.filter( and_( trans.model.Repository.table.c.name == name,
trans.model.Repository.table.c.user_id == user.id ) ) \
.first()
-def get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ):
- """Get metadata for a specified repository change set from the database"""
- # Make sure there are no duplicate records, and return the single unique record for the changeset_revision. Duplicate records were somehow
- # created in the past. The cause of this issue has been resolved, but we'll leave this method as is for a while longer to ensure all duplicate
- # records are removed.
- all_metadata_records = trans.sa_session.query( trans.model.RepositoryMetadata ) \
- .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ),
- trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \
- .order_by( trans.model.RepositoryMetadata.table.c.update_time.desc() ) \
- .all()
- if len( all_metadata_records ) > 1:
- # Delete all recrds older than the last one updated.
- for repository_metadata in all_metadata_records[ 1: ]:
- trans.sa_session.delete( repository_metadata )
- trans.sa_session.flush()
- return all_metadata_records[ 0 ]
- elif all_metadata_records:
- return all_metadata_records[ 0 ]
- return None
def get_repository_metadata_by_id( trans, id ):
"""Get repository metadata from the database"""
return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) )
@@ -762,6 +743,7 @@
if cloned_ok:
log.debug( "Generating metadata for changset revision: %s", str( ctx.rev() ) )
current_metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app,
+ repository=repository,
repository_clone_url=repository_clone_url,
relative_install_dir=repo_dir,
repository_files_dir=work_dir,
@@ -836,6 +818,7 @@
repo_dir = repository.repo_path
repo = hg.repository( get_configured_ui(), repo_dir )
metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app,
+ repository=repository,
repository_clone_url=repository_clone_url,
relative_install_dir=repo_dir,
repository_files_dir=None,
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -10,9 +10,10 @@
from galaxy.util.json import from_json_string, to_json_string
from galaxy.model.orm import *
from galaxy.util.shed_util import create_repo_info_dict, get_changectx_for_changeset, get_configured_ui, get_repository_file_contents
-from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_disk, handle_sample_files_and_load_tool_from_tmp_config, INITIAL_CHANGELOG_HASH
-from galaxy.util.shed_util import load_tool_from_config, NOT_TOOL_CONFIGS, open_repository_files_folder, reversed_lower_upper_bounded_changelog
-from galaxy.util.shed_util import reversed_upper_bounded_changelog, strip_path, to_html_escaped, update_repository, url_join
+from galaxy.util.shed_util import get_repository_metadata_by_changeset_revision, handle_sample_files_and_load_tool_from_disk
+from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_tmp_config, INITIAL_CHANGELOG_HASH, load_tool_from_config, NOT_TOOL_CONFIGS
+from galaxy.util.shed_util import open_repository_files_folder, reversed_lower_upper_bounded_changelog, reversed_upper_bounded_changelog, strip_path
+from galaxy.util.shed_util import to_html_escaped, translate_string, update_repository, url_join
from galaxy.tool_shed.encoding_util import *
from common import *
@@ -23,7 +24,6 @@
log = logging.getLogger( __name__ )
VALID_REPOSITORYNAME_RE = re.compile( "^[a-z0-9\_]+$" )
-README_FILES = [ 'readme', 'read_me', 'install' ]
class CategoryListGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
@@ -613,8 +613,10 @@
# Update repository files for browsing.
update_repository( repo )
is_malicious = changeset_is_malicious( trans, id, repository.tip )
+ metadata = self.get_metadata( trans, id, repository.tip )
return trans.fill_template( '/webapps/community/repository/browse_repository.mako',
repository=repository,
+ metadata=metadata,
commit_message=commit_message,
is_malicious=is_malicious,
webapp=webapp,
@@ -828,9 +830,11 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
repository = get_repository( trans, id )
+ metadata = self.get_metadata( trans, id, repository.tip )
if trans.user and trans.user.email:
return trans.fill_template( "/webapps/community/repository/contact_owner.mako",
repository=repository,
+ metadata=metadata,
message=message,
status=status )
else:
@@ -939,9 +943,11 @@
repository, tool, message = load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
tool_state = self.__new_state( trans )
is_malicious = changeset_is_malicious( trans, repository_id, repository.tip )
+ metadata = self.get_metadata( trans, repository_id, changeset_revision )
try:
return trans.fill_template( "/webapps/community/repository/tool_form.mako",
repository=repository,
+ metadata=metadata,
changeset_revision=changeset_revision,
tool=tool,
tool_state=tool_state,
@@ -1181,6 +1187,11 @@
trans.response.headers['Pragma'] = 'no-cache'
trans.response.headers['Expires'] = '0'
return get_repository_file_contents( file_path )
+ def get_metadata( self, trans, repository_id, changeset_revision ):
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ if repository_metadata and repository_metadata.metadata:
+ return repository_metadata.metadata
+ return None
@web.json
def get_repository_information( self, trans, repository_ids, changeset_revisions, **kwd ):
"""
@@ -1208,23 +1219,18 @@
return dict( includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies, repo_info_dicts=repo_info_dicts )
@web.expose
def get_readme( self, trans, **kwd ):
- """If the received changeset_revision includes a file named readme (case ignored), return it's contents."""
+ """If the received changeset_revision includes a readme file, return it's contents."""
repository_name = kwd[ 'name' ]
repository_owner = kwd[ 'owner' ]
changeset_revision = kwd[ 'changeset_revision' ]
- valid_filenames = [ r for r in README_FILES ]
- for r in README_FILES:
- valid_filenames.append( '%s.txt' % r )
- valid_filenames.append( '%s.txt' % repository_name )
repository = get_repository_by_name_and_owner( trans, repository_name, repository_owner )
- repo_dir = repository.repo_path
- for root, dirs, files in os.walk( repo_dir ):
- for name in files:
- if name.lower() in valid_filenames:
- f = open( os.path.join( root, name ), 'r' )
- text = f.read()
- f.close()
- return str( text )
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
+ metadata = repository_metadata.metadata
+ if metadata and 'readme' in metadata:
+ f = open( metadata[ 'readme' ], 'r' )
+ text = f.read()
+ f.close()
+ return str( text )
return ''
@web.expose
def get_tool_dependencies( self, trans, **kwd ):
@@ -1829,8 +1835,10 @@
display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) )
rra = self.get_user_item_rating( trans.sa_session, trans.user, repository, webapp_model=trans.model )
is_malicious = changeset_is_malicious( trans, id, repository.tip )
+ metadata = self.get_metadata( trans, id, repository.tip )
return trans.fill_template( '/webapps/community/repository/rate_repository.mako',
repository=repository,
+ metadata=metadata,
avg_rating=avg_rating,
display_reviews=display_reviews,
num_ratings=num_ratings,
@@ -2156,8 +2164,10 @@
# Make sure we'll view latest changeset first.
changesets.insert( 0, change_dict )
is_malicious = changeset_is_malicious( trans, id, repository.tip )
+ metadata = self.get_metadata( trans, id, repository.tip )
return trans.fill_template( '/webapps/community/repository/view_changelog.mako',
repository=repository,
+ metadata=metadata,
changesets=changesets,
is_malicious=is_malicious,
message=message,
@@ -2185,8 +2195,10 @@
for diff in patch.diff( repo, node1=ctx_parent.node(), node2=ctx.node() ):
diffs.append( to_html_escaped( diff ) )
is_malicious = changeset_is_malicious( trans, id, repository.tip )
+ metadata = self.get_metadata( trans, id, ctx_str )
return trans.fill_template( '/webapps/community/repository/view_changeset.mako',
repository=repository,
+ metadata=metadata,
ctx=ctx,
anchors=anchors,
modified=modified,
@@ -2201,6 +2213,33 @@
message=message,
status=status )
@web.expose
+ def view_readme( self, trans, id, changeset_revision, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ cntrller = params.get( 'cntrller', 'repository' )
+ webapp = params.get( 'webapp', 'community' )
+ repository = get_repository( trans, id )
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
+ metadata = repository_metadata.metadata
+ if metadata and 'readme' in metadata:
+ f = open( metadata[ 'readme' ], 'r' )
+ raw_text = f.read()
+ f.close()
+ readme_text = translate_string( raw_text, to_html=True )
+ else:
+ readme_text = ''
+ is_malicious = changeset_is_malicious( trans, id, changeset_revision )
+ return trans.fill_template( '/webapps/community/common/view_readme.mako',
+ cntrller=cntrller,
+ repository=repository,
+ changeset_revision=changeset_revision,
+ readme_text=readme_text,
+ is_malicious=is_malicious,
+ webapp=webapp,
+ message=message,
+ status=status )
+ @web.expose
def view_repository( self, trans, id, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -2318,6 +2357,8 @@
break
if guid:
tool_lineage = self.get_versions_of_tool( trans, repository, repository_metadata, guid )
+ else:
+ metadata = None
is_malicious = changeset_is_malicious( trans, repository_id, repository.tip )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
@@ -2327,6 +2368,7 @@
trans.app.config.tool_data_path = original_tool_data_path
return trans.fill_template( "/webapps/community/repository/view_tool_metadata.mako",
repository=repository,
+ metadata=metadata,
tool=tool,
tool_metadata_dict=tool_metadata_dict,
tool_lineage=tool_lineage,
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce lib/galaxy/webapps/community/controllers/workflow.py
--- a/lib/galaxy/webapps/community/controllers/workflow.py
+++ b/lib/galaxy/webapps/community/controllers/workflow.py
@@ -151,6 +151,7 @@
changeset_revision=repository_metadata.changeset_revision,
repository_metadata_id=repository_metadata_id,
workflow_name=workflow_name,
+ metadata=repository_metadata,
webapp=webapp,
message=message,
status=status )
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/browse_repository.mako
--- a/templates/admin/tool_shed_repository/browse_repository.mako
+++ b/templates/admin/tool_shed_repository/browse_repository.mako
@@ -18,6 +18,9 @@
<li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a>
%if repository.tool_dependencies:
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/browse_tool_dependency.mako
--- a/templates/admin/tool_shed_repository/browse_tool_dependency.mako
+++ b/templates/admin/tool_shed_repository/browse_tool_dependency.mako
@@ -19,8 +19,11 @@
<ul class="manage-table-actions"><li><a class="action-button" id="tool_dependency-${tool_dependency.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="tool_dependency-${tool_dependency.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a>
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
--- a/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
+++ b/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
@@ -6,8 +6,11 @@
<ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a>
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
%if repository.tool_dependencies:
<% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/manage_repository.mako
--- a/templates/admin/tool_shed_repository/manage_repository.mako
+++ b/templates/admin/tool_shed_repository/manage_repository.mako
@@ -11,6 +11,9 @@
%elif can_install:
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ), operation='install' )}">Install</a>
%else:
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
%if repository.includes_tools:
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/manage_tool_dependencies.mako
--- a/templates/admin/tool_shed_repository/manage_tool_dependencies.mako
+++ /dev/null
@@ -1,79 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<% import os %>
-
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a>
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
- %if repository.includes_tools:
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='set_tool_versions', id=trans.security.encode_id( repository.id ) )}">Set tool versions</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a>
- </div>
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Repository '${repository.name}' tool dependencies</div>
- <div class="toolFormBody">
- <div class="form-row">
- <table class="grid">
- %for tool_dependency in repository.tool_dependencies:
- <%
- name = tool_dependency.name
- version = tool_dependency.version
- type = tool_dependency.type
- installed = tool_dependency.status == 'trans.model.ToolDependency.installation_status.INSTALLED
- install_dir = tool_dependency.installation_directory( trans.app )
- %>
- <tr>
- <td bgcolor="#D8D8D8">
- <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="dependency-${tool_dependency.id}-popup">
- %if not installed:
- <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='browse', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">
- <b>Name</b>
- </a>
- <div popupmenu="dependency-${tool_dependency.id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='install', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">Install this tool dependency</a>
- </div>
- %else:
- <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='browse', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">
- <b>Name</b>
- </a>
- <div popupmenu="dependency-${tool_dependency.id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='uninstall', tool_dependency_id=trans.security.encode_id( tool_dependency.id ) )}">Uninstall this tool dependency</a>
- </div>
- %endif
- </div>
- </td>
- <td bgcolor="#D8D8D8">${name}</td>
- </tr>
- <tr><th>Version</th><td>${version}</td></tr>
- <tr><th>Type</th><td>${type}</td></tr>
- <tr>
- <th>Install directory</th>
- <td>
- %if not installed:
- This dependency is not currently installed
- %else:
- <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='browse_tool_dependency', id=trans.security.encode_id( tool_dependency.id ), repository_id=trans.security.encode_id( repository.id ) )}">
- ${install_dir}
- </a>
- %endif
- </td>
- </tr>
- <tr><th>Installed</th><td>${not installed}</td></tr>
- %endfor
- </table>
- <div style="clear: both"></div>
- </div>
- </div>
-</div>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/reselect_tool_panel_section.mako
@@ -1,6 +1,7 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" />
+<%namespace file="/webapps/community/common/common.mako" import="render_readme" />
%if message:
${render_msg( message, status )}
@@ -42,3 +43,6 @@
</form></div></div>
+%if readme_text:
+ ${render_readme( readme_text )}
+%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/select_tool_panel_section.mako
--- a/templates/admin/tool_shed_repository/select_tool_panel_section.mako
+++ b/templates/admin/tool_shed_repository/select_tool_panel_section.mako
@@ -1,6 +1,7 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/admin/tool_shed_repository/common.mako" import="render_tool_dependency_section" />
+<%namespace file="/webapps/community/common/common.mako" import="render_readme" />
%if message:
${render_msg( message, status )}
@@ -77,13 +78,5 @@
</div></div>
%if readme_text:
- <div class="toolForm">
- <div class="toolFormTitle">Repository README file (may contain important installation or license information)</div>
- <div class="toolFormBody">
- <input type="hidden" name="readme_text" value="${readme_text}"/>
- <div class="form-row">
- <pre>${readme_text}</pre>
- </div>
- </div>
- </div>
+ ${render_readme( readme_text )}
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako
--- a/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako
+++ b/templates/admin/tool_shed_repository/uninstall_tool_dependencies.mako
@@ -3,6 +3,24 @@
<% import os %>
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
+ %if repository.tool_dependencies:
+ <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a>
+ %endif
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a>
+ </div>
+</ul>
+
%if message:
${render_msg( message, status )}
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/admin/tool_shed_repository/view_tool_metadata.mako
--- a/templates/admin/tool_shed_repository/view_tool_metadata.mako
+++ b/templates/admin/tool_shed_repository/view_tool_metadata.mako
@@ -5,6 +5,9 @@
<ul class="manage-table-actions"><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup">
+ %if repository_metadata and 'readme' in repository_metadata:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='view_readme', id=trans.security.encode_id( repository.id ) )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
@@ -20,10 +23,10 @@
${render_msg( message, status )}
%endif
-%if metadata:
+%if tool_metadata:
<p/><div class="toolForm">
- <div class="toolFormTitle">${metadata[ 'name' ]} tool metadata</div>
+ <div class="toolFormTitle">${tool_metadata[ 'name' ]} tool metadata</div><div class="toolFormBody"><div class="form-row"><table width="100%">
@@ -32,41 +35,41 @@
</div><div class="form-row"><label>Name:</label>
- ${metadata[ 'name' ]}
+ ${tool_metadata[ 'name' ]}
<div style="clear: both"></div></div>
- %if 'description' in metadata:
+ %if 'description' in tool_metadata:
<div class="form-row"><label>Description:</label>
- ${metadata[ 'description' ]}
+ ${tool_metadata[ 'description' ]}
<div style="clear: both"></div></div>
%endif
- %if 'id' in metadata:
+ %if 'id' in tool_metadata:
<div class="form-row"><label>Id:</label>
- ${metadata[ 'id' ]}
+ ${tool_metadata[ 'id' ]}
<div style="clear: both"></div></div>
%endif
- %if 'guid' in metadata:
+ %if 'guid' in tool_metadata:
<div class="form-row"><label>Guid:</label>
- ${metadata[ 'guid' ]}
+ ${tool_metadata[ 'guid' ]}
<div style="clear: both"></div></div>
%endif
- %if 'version' in metadata:
+ %if 'version' in tool_metadata:
<div class="form-row"><label>Version:</label>
- ${metadata[ 'version' ]}
+ ${tool_metadata[ 'version' ]}
<div style="clear: both"></div></div>
%endif
- %if 'version_string_cmd' in metadata:
+ %if 'version_string_cmd' in tool_metadata:
<div class="form-row"><label>Version command string:</label>
- ${metadata[ 'version_string_cmd' ]}
+ ${tool_metadata[ 'version_string_cmd' ]}
<div style="clear: both"></div></div>
%endif
@@ -81,7 +84,7 @@
%for guid in tool_lineage:
<tr><td>
- %if guid == metadata[ 'guid' ]:
+ %if guid == tool_metadata[ 'guid' ]:
${guid} <b>(this tool)</b>
%else:
${guid}
@@ -100,8 +103,8 @@
</table></div><%
- if 'requirements' in metadata:
- requirements = metadata[ 'requirements' ]
+ if 'requirements' in tool_metadata:
+ requirements = tool_metadata[ 'requirements' ]
else:
requirements = None
%>
@@ -172,8 +175,8 @@
</table></div><%
- if 'tests' in metadata:
- tests = metadata[ 'tests' ]
+ if 'tests' in tool_metadata:
+ tests = tool_metadata[ 'tests' ]
else:
tests = None
%>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/common/common.mako
--- a/templates/webapps/community/common/common.mako
+++ b/templates/webapps/community/common/common.mako
@@ -13,3 +13,26 @@
%>
${html}
</%def>
+
+<%def name="render_readme( readme_text )">
+ <style type="text/css">
+ #readme_table{ table-layout:fixed;
+ width:100%;
+ overflow-wrap:normal;
+ overflow:hidden;
+ border:0px;
+ word-break:keep-all;
+ word-wrap:break-word;
+ line-break:strict; }
+ </style>
+ <div class="toolForm">
+ <div class="toolFormTitle">Repository README file (may contain important installation or license information)</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <table id="readme_table">
+ <tr><td>${readme_text}</td></tr>
+ </table>
+ </div>
+ </div>
+ </div>
+</%def>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/common/view_readme.mako
--- /dev/null
+++ b/templates/webapps/community/common/view_readme.mako
@@ -0,0 +1,88 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="render_readme" />
+
+<%
+ if webapp == 'community':
+ is_admin = trans.user_is_admin()
+ is_new = repository.is_new
+ can_contact_owner = trans.user and trans.user != repository.user
+ can_push = trans.app.security_agent.can_push( trans.user, repository )
+ can_rate = not is_new and trans.user and repository.user != trans.user
+ can_upload = can_push
+ can_download = not is_new and ( not is_malicious or can_push )
+ can_browse_contents = not is_new
+ can_view_change_log = not is_new
+ can_manage = is_admin or repository.user == trans.user
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
+%>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ %if webapp == 'community':
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a>
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp=webapp )}">Contact repository owner</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz', webapp=webapp )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2', webapp=webapp )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip', webapp=webapp )}">Download as a zip file</a>
+ %endif
+ </div>
+ %else:
+ %if cntrller=='repository':
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', operation='preview_tools_in_changeset', id=trans.security.encode_id( repository.id ), webapp=webapp )}">Preview tools for install</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a>
+ </div>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">Browse repository files</a>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get repository updates</a>
+ %if repository.includes_tools:
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='set_tool_versions', id=trans.security.encode_id( repository.id ) )}">Set tool versions</a>
+ %endif
+ %if repository.tool_dependencies:
+ <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a>
+ %endif
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a>
+ </div>
+ %endif
+ %endif
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+%if readme_text:
+ ${render_readme( readme_text )}
+%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/browse_repository.mako
--- a/templates/webapps/community/repository/browse_repository.mako
+++ b/templates/webapps/community/repository/browse_repository.mako
@@ -15,6 +15,7 @@
can_rate = trans.user and repository.user != trans.user
can_manage = is_admin or repository.user == trans.user
can_view_change_log = not is_new
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -76,6 +77,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/contact_owner.mako
--- a/templates/webapps/community/repository/contact_owner.mako
+++ b/templates/webapps/community/repository/contact_owner.mako
@@ -16,6 +16,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -42,6 +43,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/manage_repository.mako
--- a/templates/webapps/community/repository/manage_repository.mako
+++ b/templates/webapps/community/repository/manage_repository.mako
@@ -21,6 +21,7 @@
browse_label = 'Browse repository tip files'
can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip
can_reset_all_metadata = is_admin and len( repo ) > 0
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -32,35 +33,6 @@
%><%inherit file="${inherit(context)}"/>
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
<%def name="javascripts()">
${parent.javascripts()}
${h.js( "libs/jquery/jquery.rating" )}
@@ -77,6 +49,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/community/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako
@@ -16,6 +16,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -27,35 +28,6 @@
%><%inherit file="${inherit(context)}"/>
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
<%def name="javascripts()">
${parent.javascripts()}
${h.js( "libs/jquery/jquery.rating" )}
@@ -67,6 +39,9 @@
<li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revisions=changeset_revision )}">Install to local Galaxy</a></li><li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li><div popupmenu="repository-${repository.id}-popup">
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a>
+ %endif
<a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a>
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/rate_repository.mako
--- a/templates/webapps/community/repository/rate_repository.mako
+++ b/templates/webapps/community/repository/rate_repository.mako
@@ -19,6 +19,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -83,6 +84,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/tool_form.mako
--- a/templates/webapps/community/repository/tool_form.mako
+++ b/templates/webapps/community/repository/tool_form.mako
@@ -21,6 +21,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><html>
@@ -146,6 +147,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/view_changelog.mako
--- a/templates/webapps/community/repository/view_changelog.mako
+++ b/templates/webapps/community/repository/view_changelog.mako
@@ -18,6 +18,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -51,6 +52,9 @@
%else:
<a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a>
+ %endif
%if can_rate:
<a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/view_changeset.mako
--- a/templates/webapps/community/repository/view_changeset.mako
+++ b/templates/webapps/community/repository/view_changeset.mako
@@ -19,6 +19,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -52,6 +53,9 @@
%else:
<a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/view_repository.mako
--- a/templates/webapps/community/repository/view_repository.mako
+++ b/templates/webapps/community/repository/view_repository.mako
@@ -17,6 +17,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -28,35 +29,6 @@
%><%inherit file="${inherit(context)}"/>
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "jquery.rating" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style>
-</%def>
-
<%def name="javascripts()">
${parent.javascripts()}
${h.js( "libs/jquery/jquery.rating" )}
@@ -74,6 +46,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/view_tool_metadata.mako
--- a/templates/webapps/community/repository/view_tool_metadata.mako
+++ b/templates/webapps/community/repository/view_tool_metadata.mako
@@ -20,6 +20,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -59,6 +60,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp=webapp )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp=webapp )}">View change log</a>
%endif
diff -r f0eea6ef482453ccc3cc466917ae4ed93920666b -r c28c5f906c6bdbbe799cfcc559760f26029090ce templates/webapps/community/repository/view_workflow.mako
--- a/templates/webapps/community/repository/view_workflow.mako
+++ b/templates/webapps/community/repository/view_workflow.mako
@@ -22,6 +22,7 @@
browse_label = 'Browse or delete repository tip files'
else:
browse_label = 'Browse repository tip files'
+ has_readme = metadata and 'readme' in metadata
%><%!
@@ -54,6 +55,9 @@
%else:
<a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a>
%endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, webapp='community' )}">View README</a>
+ %endif
%if can_view_change_log:
<a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: compile_templates.py: handle multi-template files better; (alternate_)history: fix download popup menus
by Bitbucket 26 Sep '12
by Bitbucket 26 Sep '12
26 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/f0eea6ef4824/
changeset: f0eea6ef4824
user: carlfeberhard
date: 2012-09-26 23:42:45
summary: compile_templates.py: handle multi-template files better; (alternate_)history: fix download popup menus
affected #: 15 files
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js
+++ b/static/scripts/galaxy.base.js
@@ -66,14 +66,15 @@
};
function make_popupmenu(button_element, initial_options) {
-
/* Use the $.data feature to store options with the link element.
This allows options to be changed at a later time
*/
var element_menu_exists = (button_element.data("menu_options"));
button_element.data("menu_options", initial_options);
+
// If element already has menu, nothing else to do since HTML and actions are already set.
if (element_menu_exists) { return; }
+
button_element.bind("click.show_popup", function(e) {
// Close existing visible menus
$(".popmenu-wrapper").remove();
@@ -93,7 +94,8 @@
menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) );
}
});
- var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ).append( menu_element ).appendTo( "body" );
+ var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" )
+ .append( menu_element ).appendTo( "body" );
var x = e.pageX - wrapper.width() / 2 ;
x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 );
@@ -137,6 +139,7 @@
var confirmtext = link_dom.getAttribute( "confirm" ),
href = link_dom.getAttribute( "href" ),
target = link_dom.getAttribute( "target" );
+
if (!href) {
options[ link.text() ] = null;
} else {
@@ -161,6 +164,7 @@
};
}
});
+ // locate the element with the id corresponding to the menu's popupmenu attr
var box = $( "#" + menu.attr( 'popupmenu' ) );
// For menus with clickable link text, make clicking on the link go through instead
@@ -170,6 +174,7 @@
return true;
});
+ // attach the click events and menu box building to the box element
make_popupmenu(box, options);
box.addClass("popup");
menu.remove();
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/mvc/history.js
--- a/static/scripts/mvc/history.js
+++ b/static/scripts/mvc/history.js
@@ -1,4 +1,8 @@
-/*
+//define([
+// "../mvc/base-mvc"
+//
+//], function(){
+/* =============================================================================
Backbone.js implementation of history panel
TODO:
@@ -10,6 +14,8 @@
_render_displayApps
_render_downloadButton
widget building (popupmenu, etc.)
+ history.mako js: updater, etc.
+ have info bodies prev. opened, redisplay on refresh
don't draw body until it's first unhide event
all history.mako js -> this
@@ -30,26 +36,7 @@
move inline styles into base.less
add classes, ids on empty divs
watch the magic strings
-*/
-
-//==============================================================================
-
-//==============================================================================
-//TODO: move to Galaxy obj./namespace, decorate for current page (as GalaxyPaths)
-/*
-var Localizable = {
- localizedStrings : {},
- setLocalizedString : function( str, localizedString ){
- this.localizedStrings[ str ] = localizedString;
- },
- localize : function( str ){
- if( str in this.localizedStrings ){ return this.localizedStrings[ str ]; }
- return str;
- }
-};
-var LocalizableView = LoggingView.extend( Localizable );
-*/
-//TODO: wire up to views
+============================================================================= */
//==============================================================================
// jq plugin?
@@ -204,12 +191,7 @@
// set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
itemWrapper.find( '.tooltip' ).tooltip({ placement : 'bottom' });
- //TODO: broken
- var popupmenus = itemWrapper.find( '[popupmenu]' );
- popupmenus.each( function( i, menu ){
- menu = $( menu );
- make_popupmenu( menu );
- });
+ make_popup_menus();
//TODO: better transition/method than this...
this.$el.children().remove();
@@ -343,54 +325,23 @@
// ................................................................................ primary actions
_render_primaryActionButtons : function( buttonRenderingFuncs ){
- var primaryActionButtons = $( '<div/>' ),
+ var primaryActionButtons = $( '<div/>' ).attr( 'id', 'primary-actions-' + this.model.get( 'id' ) ),
view = this;
_.each( buttonRenderingFuncs, function( fn ){
- primaryActionButtons.append( fn.call( view ) );
+ var render_return = fn.call( view );
+ primaryActionButtons.append( render_return );
});
return primaryActionButtons;
},
_render_downloadButton : function(){
+ // don't show anything if the data's been purged
+ //if( this.model.get( 'purged' ) ){ return null; }
+
// return either: a single download icon-button (if there are no meta files)
// or a popupmenu with links to download assoc. meta files (if there are meta files)
-
- // don't show anything if the data's been purged
- if( this.model.get( 'purged' ) ){ return null; }
-
- var downloadLink = linkHTMLTemplate({
- title : 'Download',
- href : this.model.get( 'download_url' ),
- classes : [ 'icon-button', 'tooltip', 'disk' ]
- });
-
- // if no metafiles, return only the main download link
- var download_meta_urls = this.model.get( 'download_meta_urls' );
- if( !download_meta_urls ){
- return downloadLink;
- }
-
- // build the popupmenu for downloading main, meta files
- var popupmenu = $( '<div popupmenu="dataset-' + this.model.get( 'id' ) + '-popup"></div>' );
- popupmenu.append( linkHTMLTemplate({
- text : 'Download Dataset',
- title : 'Download',
- href : this.model.get( 'download_url' ),
- classes : [ 'icon-button', 'tooltip', 'disk' ]
- }));
- popupmenu.append( '<a>Additional Files</a>' );
- for( file_type in download_meta_urls ){
- popupmenu.append( linkHTMLTemplate({
- text : 'Download ' + file_type,
- href : download_meta_urls[ file_type ],
- classes : [ 'action-button' ]
- }));
- }
- var menuButton = $( ( '<div style="float:left;" class="menubutton split popup"'
- + ' id="dataset-${dataset_id}-popup"></div>' ) );
- menuButton.append( downloadLink );
- popupmenu.append( menuButton );
- return popupmenu;
+ var downloadLinkHTML = HistoryItemView.templates.downloadLinks( this.model.toJSON() );
+ return $( downloadLinkHTML );
},
//NOTE: button renderers have the side effect of caching their IconButtonViews to this view
@@ -451,8 +402,12 @@
// ................................................................................ secondary actions
_render_secondaryActionButtons : function( buttonRenderingFuncs ){
// move to the right (same level as primary)
- var secondaryActionButtons = $( '<div style="float: right;"></div>' ),
+ var secondaryActionButtons = $( '<div/>' ),
view = this;
+ secondaryActionButtons
+ .attr( 'style', 'float: right;' )
+ .attr( 'id', 'secondary-actions-' + this.model.get( 'id' ) );
+
_.each( buttonRenderingFuncs, function( fn ){
secondaryActionButtons.append( fn.call( view ) );
});
@@ -817,7 +772,8 @@
hdaSummary : 'template-history-hdaSummary',
failedMetadata : 'template-history-failedMetaData',
tagArea : 'template-history-tagArea',
- annotationArea : 'template-history-annotationArea'
+ annotationArea : 'template-history-annotationArea',
+ downloadLinks : 'template-history-downloadLinks'
}
});
@@ -967,163 +923,10 @@
//==============================================================================
-function createMockHistoryData(){
- mockHistory = {};
- mockHistory.data = {
-
- template : {
- id : 'a799d38679e985db',
- name : 'template',
- data_type : 'fastq',
- file_size : 226297533,
- genome_build : '?',
- metadata_data_lines : 0,
- metadata_dbkey : '?',
- metadata_sequences : 0,
- misc_blurb : '215.8 MB',
- misc_info : 'uploaded fastq file (misc_info)',
- model_class : 'HistoryDatasetAssociation',
- download_url : '',
- state : 'ok',
- visible : true,
- deleted : false,
- purged : false,
-
- hid : 0,
- //TODO: move to history
- for_editing : true,
- //for_editing : false,
-
- //?? not needed
- //can_edit : true,
- //can_edit : false,
-
- accessible : true,
-
- //TODO: move into model functions (build there (and cache?))
- //!! be careful with adding these accrd. to permissions
- //!! IOW, don't send them via template/API if the user doesn't have perms to use
- //!! (even if they don't show up)
- undelete_url : '',
- purge_url : '',
- unhide_url : '',
-
- display_url : 'example.com/display',
- edit_url : 'example.com/edit',
- delete_url : 'example.com/delete',
-
- show_params_url : 'example.com/show_params',
- rerun_url : 'example.com/rerun',
-
- retag_url : 'example.com/retag',
- annotate_url : 'example.com/annotate',
-
- peek : [
- '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>',
- '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>',
- '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>',
- '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>',
- '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>',
- '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
- '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
- '</table>'
- ].join( '' )
- }
-
- };
- _.extend( mockHistory.data, {
-
- notAccessible :
- _.extend( _.clone( mockHistory.data.template ),
- { accessible : false }),
-
- //deleted, purged, visible
- deleted :
- _.extend( _.clone( mockHistory.data.template ),
- { deleted : true,
- delete_url : '',
- purge_url : 'example.com/purge',
- undelete_url : 'example.com/undelete' }),
- purgedNotDeleted :
- _.extend( _.clone( mockHistory.data.template ),
- { purged : true,
- delete_url : '' }),
- notvisible :
- _.extend( _.clone( mockHistory.data.template ),
- { visible : false,
- unhide_url : 'example.com/unhide' }),
-
- hasDisplayApps :
- _.extend( _.clone( mockHistory.data.template ),
- { display_apps : {
- 'display in IGB' : {
- Web: "/display_application/63cd3858d057a6d1/igb_bam/Web",
- Local: "/display_application/63cd3858d057a6d1/igb_bam/Local"
- }
- }
- }
- ),
- canTrackster :
- _.extend( _.clone( mockHistory.data.template ),
- { trackster_urls : {
- 'data-url' : "example.com/trackster-data",
- 'action-url' : "example.com/trackster-action",
- 'new-url' : "example.com/trackster-new"
- }
- }
- ),
- zeroSize :
- _.extend( _.clone( mockHistory.data.template ),
- { file_size : 0 }),
-
- hasMetafiles :
- _.extend( _.clone( mockHistory.data.template ), {
- download_meta_urls : {
- 'bam_index' : "example.com/bam-index"
- }
- }),
-
- //states
- upload :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.UPLOAD }),
- queued :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.QUEUED }),
- running :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.RUNNING }),
- empty :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.EMPTY }),
- error :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.ERROR,
- report_error_url: 'example.com/report_err' }),
- discarded :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.DISCARDED }),
- setting_metadata :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.SETTING_METADATA }),
- failed_metadata :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.FAILED_METADATA })
-/*
-*/
- });
-
- $( document ).ready( function(){
- //mockHistory.views.deleted.logger = console;
- mockHistory.items = {};
- mockHistory.views = {};
- for( key in mockHistory.data ){
- mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] );
- mockHistory.items[ key ].set( 'name', key );
- mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] });
- //console.debug( 'view: ', mockHistory.views[ key ] );
- $( 'body' ).append( mockHistory.views[ key ].render() );
- }
- });
-}
-
+//return {
+// HistoryItem : HistoryItem,
+// HitoryItemView : HistoryItemView,
+// HistoryCollection : HistoryCollection,
+// History : History,
+// HistoryView : HistoryView
+//};});
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compile_templates.py
--- a/static/scripts/templates/compile_templates.py
+++ b/static/scripts/templates/compile_templates.py
@@ -46,153 +46,99 @@
from glob import glob
from subprocess import call
-from shutil import copyfile
-from os import path
+import os
from optparse import OptionParser
-from HTMLParser import HTMLParser
+import re
-import logging
-log = logging.getLogger( __name__ )
+import logging as log
+log.basicConfig(
+ #level = log.DEBUG,
+ name = __name__
+)
COMPILED_DIR = 'compiled'
COMPILED_EXT = '.js'
COMPILE_CMD_STR = "handlebars %s -f %s"
COMPILE_MINIMIZE_SWITCH = ' -m'
+TEMPLATE_TAG = 'script'
+TEMPLATE_TYPE = 'text/template'
+HELPER_TYPE = 'text/javascript'
+
# both of these are off by default for backward compat
DEFAULT_MINIMIZATION = False
DEFAULT_MULTI_EXT = None #'.html'
# ------------------------------------------------------------------------------
-class HTMLMultiTemplateParser( HTMLParser ):
- """Parses multiple templates from an HTML file, saving them to a map of:
- { id : template_text, ... }
+def parse_html_tag_attrs( string ):
+ attrs = {}
+ for match in re.finditer( r'(?P<key>\w+?)=[\'|\"](?P<val>.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ):
+ match = match.groupdict()
+ key = match[ 'key' ]
+ val = match[ 'val' ]
+ attrs[ key ] = val
+ return attrs
+
+def split_on_html_tag( string, tag ):
+ tag_pattern = r'<%s\s*(?P<attrs>.*?)>(?P<body>.*?)</%s>' % ( tag, tag )
+ log.debug( tag_pattern )
+ tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL )
+
+ found_list = re.findall( tag_pattern, string )
+ for attrs, body in found_list:
+ yield ( parse_html_tag_attrs( attrs ), body )
+
+def filter_on_tag_type( generator, type_attr_to_match ):
+ for attrs, body in generator:
+ log.debug( 'attrs: %s', str( attrs ) )
+ if( ( 'type' in attrs )
+ and ( attrs[ 'type' ] == type_attr_to_match ) ):
+ yield attrs, body
+
- Templates must:
- * be within the TEMPLATE_TAG
- * TEMPLATE_TAG must have a type attribute
- * that attr must == TEMPLATE_TYPE
- * TEMPLATE_TAG cannot be nested within one another
- * TEMPLATE_TAG must have an id attribute
- """
- TEMPLATE_TAG = 'script'
- TEMPLATE_TYPES = [ 'text/template' ]
-
- HELPER_TAG = 'script'
- HELPER_TYPES = [ 'text/javascript' ]
-
- def __init__( self ):
- HTMLParser.__init__( self )
- self.templates = {}
- self.curr_template_id = None
- self.template_data = ''
-
- self.helpers = {}
- self.curr_helper_id = None
- self.helper_data = ''
-
- def is_template_tag( self, tag, attr_dict ):
- # both tag and type attr must match
- return ( ( tag == self.TEMPLATE_TAG )
- and ( 'type' in attr_dict )
- and ( attr_dict[ 'type' ] in self.TEMPLATE_TYPES ) )
-
- def is_helper_tag( self, tag, attr_dict ):
- # both tag and type attr must match
- return ( ( tag == self.HELPER_TAG )
- and ( 'type' in attr_dict )
- and ( attr_dict[ 'type' ] in self.HELPER_TYPES ) )
-
- def handle_starttag( self, tag, attrs ):
- attr_dict = dict( attrs )
- if self.is_template_tag( tag, attr_dict ):
- log.debug( "\t template tag: %s, %s", tag, str( attr_dict ) );
-
- # as far as I know these tags can't/shouldn't nest/overlap
- #pre: not already inside a template/helper tag
- assert self.curr_template_id == None, "Found nested template tag: %s" % ( self.curr_template_id )
- assert self.curr_helper_id == None, "Found template tag inside helper: %s" % ( self.curr_helper_id )
- #pre: must have an id
- assert 'id' in attr_dict, "No id attribute in template: " + str( attr_dict )
-
- self.curr_template_id = attr_dict[ 'id' ]
-
- elif self.is_helper_tag( tag, attr_dict ):
- log.debug( "\t helper tag: %s, %s", tag, str( attr_dict ) );
-
- #pre: not already inside a template/helper tag
- assert self.curr_helper_id == None, "Found nested helper tag: %s" % ( self.curr_helper_id )
- assert self.curr_template_id == None, "Found helper tag inside template: %s" % ( self.curr_template_id )
- #pre: must have an id
- assert 'id' in attr_dict, "No id attribute in helper: " + str( attr_dict )
-
- self.curr_helper_id = attr_dict[ 'id' ]
-
- def handle_endtag( self, tag ):
- if( ( tag == self.TEMPLATE_TAG )
- and ( self.curr_template_id ) ):
- log.debug( "\t ending template tag :", tag, self.curr_template_id );
-
- # store the template data by the id
- if self.template_data:
- self.templates[ self.curr_template_id ] = self.template_data
-
- #! reset for next template
- self.curr_template_id = None
- self.template_data = ''
-
- elif( ( tag == self.HELPER_TAG )
- and ( self.curr_helper_id ) ):
- log.debug( "\t ending helper tag :", tag, self.curr_template_id );
-
- # store the template data by the id
- if self.helper_data:
- self.helpers[ self.curr_helper_id ] = self.helper_data
-
- #! reset for next template
- self.curr_helper_id = None
- self.helper_data = ''
-
- def handle_data(self, data):
- data = data.strip()
- if data:
- if self.curr_template_id:
- log.debug( "\t template text :", data );
- self.template_data += data
-
- elif self.curr_helper_id:
- log.debug( "\t helper js fn :", data );
- self.helper_data += data
-
-
# ------------------------------------------------------------------------------
def break_multi_template( multi_template_filename ):
"""parse the multi template, writing each template into a new handlebars tmpl and returning their names"""
template_filenames = []
- parser = HTMLMultiTemplateParser()
# parse the multi template
print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename )
with open( multi_template_filename, 'r' ) as multi_template_file:
- # wish I could use a gen here
- parser.feed( multi_template_file.read() )
+ multi_template_file_text = multi_template_file.read()
- # after breaking, write each indiv. template and save the names
- for template_id, template_text in parser.templates.items():
+ # write a template file for each template (name based on id in tag)
+ tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
+ for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ):
+ if( 'id' not in attrs ):
+ log.warning( 'Template has no "id". attrs: %s' %( str( attrs ) ) )
+ continue
+
+ template_id = attrs[ 'id' ]
+ template_text = template_text.strip()
handlebar_template_filename = template_id + '.handlebars'
with open( handlebar_template_filename, 'w' ) as handlebar_template_file:
handlebar_template_file.write( template_text )
+ log.debug( "%s\n%s\n", template_id, template_text )
template_filenames.append( handlebar_template_filename )
- # write all helpers to a 'helper-' prefixed js file in the compilation dir
- if parser.helpers:
- helper_filename = 'helpers-' + path.splitext( multi_template_filename )[0] + '.js'
- helper_filename = path.join( COMPILED_DIR, helper_filename )
+ ## write all helpers to a single 'helper-' prefixed js file in the compilation dir
+ helper_fns = []
+ # same tag, different type
+ tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG )
+ for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ):
+ helper_text = helper_text.strip()
+ print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' )
+
+ helper_fns.append( helper_text )
+
+ if helper_fns:
+ # prefix original filename (in compiled dir) and write all helper funcs to that file
+ helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js'
+ helper_filename = os.path.join( COMPILED_DIR, helper_filename )
with open( helper_filename, 'w' ) as helper_file:
- for helper_fn_name, helper_fn in parser.helpers.items():
- print '(helper)', helper_fn_name
- helper_file.write( helper_fn + '\n' )
+ helper_file.write( '\n'.join( helper_fns ) )
+ print '(helper functions written to %s)' % helper_filename
print '\n'.join( template_filenames )
return template_filenames
@@ -204,8 +150,8 @@
Use the basename of the template file for the outputed js.
"""
- template_basename = path.splitext( path.split( template_filename )[1] )[0]
- compiled_filename = path.join( COMPILED_DIR, template_basename + COMPILED_EXT )
+ template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0]
+ compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT )
command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename )
if minimize:
@@ -233,6 +179,7 @@
# if desired, break up any passed-in or found multi template files
# adding the names of the new single templates to those needing compilation
+ multi_template_template_filenames = []
if options.multi_ext:
multi_templates = []
if len( args ) >= 1:
@@ -241,10 +188,10 @@
multi_templates = glob( '*' + options.multi_ext )
for multi_template_filename in multi_templates:
- handlebars_templates.extend( break_multi_template( multi_template_filename ) )
+ multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) )
# unique filenames only (Q&D)
- handlebars_templates = list( set( handlebars_templates ) )
+ handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) )
# compile the templates
print "\nCompiling templates:"
@@ -260,6 +207,12 @@
print ',\n'.join( filenames_w_possible_errors )
print "\nCall this script with the '-h' for more help"
+ # delete multi template intermediate files
+ print "\nCleaning up intermediate multi-template template files:"
+ for filename in multi_template_template_filenames:
+ print 'removing', filename
+ os.remove( filename )
+
# ------------------------------------------------------------------------------
if __name__ == '__main__':
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compiled/helpers-common-templates.js
--- a/static/scripts/templates/compiled/helpers-common-templates.js
+++ b/static/scripts/templates/compiled/helpers-common-templates.js
@@ -3,6 +3,11 @@
Handlebars.registerPartial( 'clearFloatDiv', function( options ){
return '<div class="clear"></div>';
});
+/** Renders a warning in a (mostly css) highlighted, iconned warning box
+ */
+Handlebars.registerHelper( 'warningmessagesmall', function( options ){
+ return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>'
+});
/** Renders a glx style icon-button (see IconButton in mvc/ui.js)
* can be used in either of the following ways:
* within a template: {{> iconButton buttonData}}
@@ -29,9 +34,4 @@
buffer += '>' + ( ( buttonData.enabled )?( '</a>' ):( '</span>' ) );
return buffer;
-});
-/** Renders a warning in a (mostly css) highlighted, iconned warning box
- */
-Handlebars.registerHelper( 'warningmessagesmall', function( options ){
- return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>'
-});
+});
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compiled/template-history-downloadLinks.js
--- /dev/null
+++ b/static/scripts/templates/compiled/template-history-downloadLinks.js
@@ -0,0 +1,55 @@
+(function() {
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
+templates['template-history-downloadLinks'] = template(function (Handlebars,depth0,helpers,partials,data) {
+ helpers = helpers || Handlebars.helpers;
+ var stack1, functionType="function", escapeExpression=this.escapeExpression, self=this;
+
+function program1(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div popupmenu=\"dataset-";
+ foundHelper = helpers.id;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "-popup\">\n <a class=\"action-button\" href=\"";
+ foundHelper = helpers.download_url;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\">Download Dataset</a>\n <a>Additional Files</a>\n ";
+ stack1 = depth0.meta_files;
+ stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n</div>\n<div style=\"float:left;\" class=\"menubutton split popup\" id=\"dataset-";
+ foundHelper = helpers.id;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "-popup\">\n <a href=\"";
+ foundHelper = helpers.download_url;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n</div>\n";
+ return buffer;}
+function program2(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n <a class=\"action-button\" href=\"";
+ foundHelper = helpers.meta_download_url;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.meta_download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\">Download ";
+ foundHelper = helpers.meta_file_type;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.meta_file_type; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "</a>\n ";
+ return buffer;}
+
+function program4(depth0,data) {
+
+
+ return "\n <a href=\"\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n";}
+
+ stack1 = depth0.meta_files;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(4, program4, data),fn:self.program(1, program1, data)});
+ if(stack1 || stack1 === 0) { return stack1; }
+ else { return ''; }});
+})();
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/history-templates.html
--- a/static/scripts/templates/history-templates.html
+++ b/static/scripts/templates/history-templates.html
@@ -70,3 +70,21 @@
</div></script>
+<script type="text/template" class="template-history" id="template-history-downloadLinks">
+{{#if meta_files}}
+<div popupmenu="dataset-{{id}}-popup">
+ <a class="action-button" href="{{download_url}}">Download Dataset</a>
+ <a>Additional Files</a>
+ {{#each meta_files}}
+ <a class="action-button" href="{{meta_download_url}}">Download {{meta_file_type}}</a>
+ {{/each}}
+</div>
+<div style="float:left;" class="menubutton split popup" id="dataset-{{id}}-popup">
+ <a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a>
+</div>
+{{else}}
+ <a href="" title="Download" class="icon-button disk tooltip"></a>
+{{/if}}
+</script>
+
+
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-annotationArea.handlebars
--- a/static/scripts/templates/template-history-annotationArea.handlebars
+++ /dev/null
@@ -1,7 +0,0 @@
-{{! TODO: move to mvc/annotations.js templates, editable-text }}
-<div id="{{ id }}-annotation-area" class="annotation-area" style="display: none;">
- <strong>Annotation:</strong>
- <div id="{{ id }}-anotation-elt" class="annotation-elt tooltip editable-text"
- style="margin: 1px 0px 1px 0px" title="Edit dataset annotation">
- </div>
-</div>
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-failedMetaData.handlebars
--- a/static/scripts/templates/template-history-failedMetaData.handlebars
+++ /dev/null
@@ -1,4 +0,0 @@
-{{#warningmessagesmall}}
-An error occurred setting the metadata for this dataset.
-You may be able to <a href="{{ edit_url }}" target="galaxy_main">set it manually or retry auto-detection</a>.
-{{/warningmessagesmall}}
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-hdaSummary.handlebars
--- a/static/scripts/templates/template-history-hdaSummary.handlebars
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="hda-summary">
- {{ misc_blurb }}<br />
- format: <span class="{{ data_type }}">{{ data_type }}</span>,
- database:
- {{#if dbkey_unknown_and_editable }}
- <a href="{{ edit_url }}" target="galaxy_main">{{ metadata_dbkey }}</a>
- {{else}}
- <span class="{{ metadata_dbkey }}">{{ metadata_dbkey }}</span>
- {{/if}}
-</div>
-{{#if misc_info}}
-<div class="hda-info">{{ misc_info }}</div>
-{{/if}}
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-tagArea.handlebars
--- a/static/scripts/templates/template-history-tagArea.handlebars
+++ /dev/null
@@ -1,6 +0,0 @@
-{{! TODO: move to mvc/tag.js templates }}
-<div class="tag-area" style="display: none;">
- <strong>Tags:</strong>
- <div class="tag-elt">
- </div>
-</div>
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-titleLink.handlebars
--- a/static/scripts/templates/template-history-titleLink.handlebars
+++ /dev/null
@@ -1,1 +0,0 @@
-<a href="javascript:void(0);"><span class="historyItemTitle">{{ hid }}: {{ name }}</span></a>
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-warning-messages.handlebars
--- a/static/scripts/templates/template-history-warning-messages.handlebars
+++ /dev/null
@@ -1,23 +0,0 @@
-{{#if deleted}}{{#warningmessagesmall}}
- This dataset has been deleted.
- {{#if undelete_url}}
- Click <a href="{{ undelete_url }}" class="historyItemUndelete" id="historyItemUndeleter-{{ id }}"
- target="galaxy_history">here</a> to undelete it
- {{#if purge_url}}
- or <a href="{{ purge_url }}" class="historyItemPurge" id="historyItemPurger-{{ id }}"
- target="galaxy_history">here</a> to immediately remove it from disk
- {{/if}}
- {{/if}}
-{{/warningmessagesmall}}{{/if}}
-
-{{#if purged}}{{#warningmessagesmall}}
- This dataset has been deleted and removed from disk.
-{{/warningmessagesmall}}{{/if}}
-
-{{#unless visible}}{{#warningmessagesmall}}
- This dataset has been hidden.
- {{#if unhide_url}}
- Click <a href="{{ unhide_url }}" class="historyItemUnhide" id="historyItemUnhider-{{ id }}"
- target="galaxy_history">here</a> to unhide it
- {{/if}}
-{{/warningmessagesmall}}{{/unless}}
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-iconButton.handlebars
--- a/static/scripts/templates/template-iconButton.handlebars
+++ /dev/null
@@ -1,2 +0,0 @@
-{{! alternate template-based icon-button }}
-{{> iconButton this}}
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-warningmessagesmall.handlebars
--- a/static/scripts/templates/template-warningmessagesmall.handlebars
+++ /dev/null
@@ -1,2 +0,0 @@
-{{! renders a warning in a (mostly css) highlighted, iconned warning box }}
- <div class="warningmessagesmall"><strong>{{{ warning }}}</strong></div>
\ No newline at end of file
diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b templates/root/alternate_history.mako
--- a/templates/root/alternate_history.mako
+++ b/templates/root/alternate_history.mako
@@ -7,6 +7,40 @@
## ?? add: if string != _(string)
</%def>
+##<%def name="render_download_links( data, dataset_id )">
+## ##
+## %if data.purged: return
+## <%
+## from galaxy.datatypes.metadata import FileParameter
+## download_url = h.url_for( controller='/dataset', action='display', dataset_id=dataset_id, to_ext=data.ext )
+## meta_files = []
+## for k in data.metadata.spec.keys():
+## if isinstance( data.metadata.spec[ k ].param, FileParameter ):
+## file_type = k
+## download_url = h.url_for( controller='/dataset', action='get_metadata_file',
+## hda_id=dataset_id, metadata_name=file_type )
+## meta_files.append( ( file_type, download_url ) )
+## %>
+##
+## %if meta_files:
+## <div popupmenu="dataset-${dataset_id}-popup">
+## <a class="action-button" href="${download_url}">Download Dataset</a>
+##
+## <a>Additional Files</a>
+## %for meta_file_type, meta_download_url in zip( meta_download_types, meta_download_urls ):
+## <a class="action-button" href="${meta_download_url}">Download ${meta_file_type}</a>
+## %endfor
+##
+## <div style="float:left;" class="menubutton split popup" id="dataset-${dataset_id}-popup">
+## <a href="${download_url}" title='${_("Download")}' class="icon-button disk tooltip"></a>
+## </div>
+## </div>
+##
+## %else
+## <a href="${download_url}" title='${_("Download")}' class="icon-button disk tooltip"></a>
+## %endif
+##</%def>
+
<%def name="get_page_localized_strings()">
## a list of localized strings used in the backbone views, etc. (to be loaded and cached)
##! change on per page basis
@@ -54,33 +88,34 @@
<%def name="get_urls_for_hda( hda, encoded_data_id, for_editing )"><%
from galaxy.datatypes.metadata import FileParameter
+ #print '\n', hda.name
data_dict = {}
def add_to_data( **kwargs ):
data_dict.update( kwargs )
- # download links (for both main hda and associated meta files)
- if hda.has_data():
- add_to_data( download_url=h.url_for( controller='/dataset', action='display',
- dataset_id=encoded_data_id, to_ext=hda.ext ) )
-
- download_meta_urls = {}
- for file_type in hda.metadata.spec.keys():
- if not isinstance( hda.metadata.spec[ file_type ].param, FileParameter ):
- continue
-
- download_meta_urls[ file_type ] = h.url_for( controller='/dataset', action='get_metadata_file',
- hda_id=encoded_data_id, metadata_name=file_type )
- if download_meta_urls:
- #TODO:?? needed? isn't this the same as download_url?
- add_to_data( download_dataset_url=h.url_for( controller='dataset', action='display',
- dataset_id=encoded_data_id, to_ext=hda.ext ) )
- add_to_data( download_meta_urls=download_meta_urls )
-
#TODO??: better way to do urls (move into js galaxy_paths (decorate) - _not_ dataset specific)
deleted = hda.deleted
purged = hda.purged
+ # download links (for both main hda and associated meta files)
+ if not hda.purged:
+ add_to_data( download_url=h.url_for( controller='/dataset', action='display',
+ dataset_id=encoded_data_id, to_ext=hda.ext ) )
+
+ meta_files = []
+ for k in hda.metadata.spec.keys():
+ if isinstance( hda.metadata.spec[ k ].param, FileParameter ):
+ file_type = k
+ download_url = h.url_for( controller='/dataset', action='get_metadata_file',
+ hda_id=encoded_data_id, metadata_name=file_type )
+ meta_files.append( dict( meta_file_type=file_type, meta_download_url=download_url ) )
+
+ if meta_files:
+ print hda.name, meta_files
+ add_to_data( meta_files=meta_files )
+
+
#purged = purged or hda.dataset.purged //??
# all of these urls are 'datasets/data_id/<action>
@@ -305,7 +340,8 @@
"template-history-hdaSummary",
"template-history-failedMetadata",
"template-history-tagArea",
- "template-history-annotationArea"
+ "template-history-annotationArea",
+ "template-history-downloadLinks"
)}
## if using in-dom templates they need to go here (before the Backbone classes are defined)
@@ -339,6 +375,7 @@
createMockHistoryData();
return;
+ //TODO: handle empty history
} else if ( window.USE_CURR_DATA ){
if( console && console.debug ){ console.debug( '\t using current history data' ); }
glx_history = new History( pageData.history ).loadDatasetsAsHistoryItems( pageData.hdas );
@@ -409,3 +446,163 @@
</%def><body class="historyPage"></body>
+
+<script type="text/javascript">
+function createMockHistoryData(){
+ mockHistory = {};
+ mockHistory.data = {
+
+ template : {
+ id : 'a799d38679e985db',
+ name : 'template',
+ data_type : 'fastq',
+ file_size : 226297533,
+ genome_build : '?',
+ metadata_data_lines : 0,
+ metadata_dbkey : '?',
+ metadata_sequences : 0,
+ misc_blurb : '215.8 MB',
+ misc_info : 'uploaded fastq file (misc_info)',
+ model_class : 'HistoryDatasetAssociation',
+ download_url : '',
+ state : 'ok',
+ visible : true,
+ deleted : false,
+ purged : false,
+
+ hid : 0,
+ //TODO: move to history
+ for_editing : true,
+ //for_editing : false,
+
+ //?? not needed
+ //can_edit : true,
+ //can_edit : false,
+
+ accessible : true,
+
+ //TODO: move into model functions (build there (and cache?))
+ //!! be careful with adding these accrd. to permissions
+ //!! IOW, don't send them via template/API if the user doesn't have perms to use
+ //!! (even if they don't show up)
+ undelete_url : '',
+ purge_url : '',
+ unhide_url : '',
+
+ display_url : 'example.com/display',
+ edit_url : 'example.com/edit',
+ delete_url : 'example.com/delete',
+
+ show_params_url : 'example.com/show_params',
+ rerun_url : 'example.com/rerun',
+
+ retag_url : 'example.com/retag',
+ annotate_url : 'example.com/annotate',
+
+ peek : [
+ '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>',
+ '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>',
+ '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>',
+ '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>',
+ '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>',
+ '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
+ '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
+ '</table>'
+ ].join( '' )
+ }
+
+ };
+ _.extend( mockHistory.data, {
+
+ notAccessible :
+ _.extend( _.clone( mockHistory.data.template ),
+ { accessible : false }),
+
+ //deleted, purged, visible
+ deleted :
+ _.extend( _.clone( mockHistory.data.template ),
+ { deleted : true,
+ delete_url : '',
+ purge_url : 'example.com/purge',
+ undelete_url : 'example.com/undelete' }),
+ purgedNotDeleted :
+ _.extend( _.clone( mockHistory.data.template ),
+ { purged : true,
+ delete_url : '' }),
+ notvisible :
+ _.extend( _.clone( mockHistory.data.template ),
+ { visible : false,
+ unhide_url : 'example.com/unhide' }),
+
+ hasDisplayApps :
+ _.extend( _.clone( mockHistory.data.template ),
+ { display_apps : {
+ 'display in IGB' : {
+ Web: "/display_application/63cd3858d057a6d1/igb_bam/Web",
+ Local: "/display_application/63cd3858d057a6d1/igb_bam/Local"
+ }
+ }
+ }
+ ),
+ canTrackster :
+ _.extend( _.clone( mockHistory.data.template ),
+ { trackster_urls : {
+ 'data-url' : "example.com/trackster-data",
+ 'action-url' : "example.com/trackster-action",
+ 'new-url' : "example.com/trackster-new"
+ }
+ }
+ ),
+ zeroSize :
+ _.extend( _.clone( mockHistory.data.template ),
+ { file_size : 0 }),
+
+ hasMetafiles :
+ _.extend( _.clone( mockHistory.data.template ), {
+ download_meta_urls : {
+ 'bam_index' : "example.com/bam-index"
+ }
+ }),
+
+ //states
+ upload :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.UPLOAD }),
+ queued :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.QUEUED }),
+ running :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.RUNNING }),
+ empty :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.EMPTY }),
+ error :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.ERROR,
+ report_error_url: 'example.com/report_err' }),
+ discarded :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.DISCARDED }),
+ setting_metadata :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.SETTING_METADATA }),
+ failed_metadata :
+ _.extend( _.clone( mockHistory.data.template ),
+ { state : HistoryItem.STATES.FAILED_METADATA })
+/*
+*/
+ });
+
+ //mockHistory.views.deleted.logger = console;
+ mockHistory.items = {};
+ mockHistory.views = {};
+ for( key in mockHistory.data ){
+ mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] );
+ mockHistory.items[ key ].set( 'name', key );
+ mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] });
+ //console.debug( 'view: ', mockHistory.views[ key ] );
+ $( 'body' ).append( mockHistory.views[ key ].render() );
+ }
+}
+</script>
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Update Cuffdiff wrapper to support v2.0 and add multi-read correction option.
by Bitbucket 26 Sep '12
by Bitbucket 26 Sep '12
26 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/9c29a51ec0b1/
changeset: 9c29a51ec0b1
user: jgoecks
date: 2012-09-26 17:08:59
summary: Update Cuffdiff wrapper to support v2.0 and add multi-read correction option.
affected #: 5 files
diff -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff test-data/cuffdiff_out10.txt
--- a/test-data/cuffdiff_out10.txt
+++ b/test-data/cuffdiff_out10.txt
@@ -1,88 +1,88 @@
test_id gene_id gene locus sample_1 sample_2 status value_1 value_2 sqrt(JS) test_stat p_value q_value significant
-XLOC_000001 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000002 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000003 XLOC_000003 - chr1:3111545-3111576 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000004 XLOC_000004 - chr1:3174765-3174792 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000005 XLOC_000005 - chr1:3187401-3187428 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000006 XLOC_000006 - chr1:3188521-3188548 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000007 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000008 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000009 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000010 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000011 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000012 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000013 XLOC_000013 - chr1:3192649-3192676 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000014 XLOC_000014 - chr1:3192731-3192811 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000015 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000016 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000017 XLOC_000017 - chr1:3194302-3194329 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000018 XLOC_000018 - chr1:3194706-3194733 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000019 XLOC_000019 - chr1:3195083-3195110 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000020 XLOC_000020 - chr1:3195450-3195477 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000021 XLOC_000021 - chr1:3197089-3197116 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000022 XLOC_000022 - chr1:3197246-3197273 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000023 XLOC_000023 - chr1:3197346-3197373 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000024 XLOC_000024 - chr1:3197425-3197452 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000025 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000026 XLOC_000026 - chr1:3200325-3200352 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000027 XLOC_000027 - chr1:3200430-3200457 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000028 XLOC_000028 - chr1:3201007-3201039 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000029 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000030 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000031 XLOC_000031 - chr1:3201672-3201699 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000032 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000033 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000034 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000035 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000036 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000037 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000038 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000039 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000040 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000041 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000042 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000043 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000044 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000045 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000046 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000047 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000048 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000049 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000050 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000051 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000052 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000053 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000054 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000055 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000056 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000057 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000058 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000059 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000060 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000061 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000062 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000063 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000064 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000065 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000066 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000067 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000068 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000069 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000070 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000071 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000072 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000073 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000074 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000075 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000076 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000077 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000078 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000079 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000080 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000081 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000082 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000083 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000084 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000085 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000086 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 NOTEST 0 0 0 0 0 1 no
-XLOC_000087 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 NOTEST 0 0 0 0 0 1 no
+XLOC_000001 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000002 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000003 XLOC_000003 - chr1:3111545-3111576 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000004 XLOC_000004 - chr1:3174765-3174792 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000005 XLOC_000005 - chr1:3187401-3187428 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000006 XLOC_000006 - chr1:3188521-3188548 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000007 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000008 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000009 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000010 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000011 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000012 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000013 XLOC_000013 - chr1:3192649-3192676 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000014 XLOC_000014 - chr1:3192731-3192811 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000015 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000016 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000017 XLOC_000017 - chr1:3194302-3194329 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000018 XLOC_000018 - chr1:3194706-3194733 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000019 XLOC_000019 - chr1:3195083-3195110 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000020 XLOC_000020 - chr1:3195450-3195477 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000021 XLOC_000021 - chr1:3197089-3197116 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000022 XLOC_000022 - chr1:3197246-3197273 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000023 XLOC_000023 - chr1:3197346-3197373 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000024 XLOC_000024 - chr1:3197425-3197452 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000025 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000026 XLOC_000026 - chr1:3200325-3200352 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000027 XLOC_000027 - chr1:3200430-3200457 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000028 XLOC_000028 - chr1:3201007-3201039 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000029 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000030 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000031 XLOC_000031 - chr1:3201672-3201699 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000032 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000033 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000034 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000035 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000036 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000037 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000038 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000039 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000040 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000041 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000042 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000043 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000044 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000045 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000046 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000047 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000048 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000049 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000050 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000051 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000052 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000053 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000054 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000055 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000056 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000057 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000058 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000059 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000060 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000061 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000062 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000063 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000064 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000065 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000066 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000067 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000068 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000069 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000070 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000071 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000072 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000073 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000074 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 1 1 no
+XLOC_000075 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000076 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000077 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000078 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000079 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000080 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000081 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000082 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000083 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000084 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000085 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000086 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 LOWDATA 0 0 0 0 0 1 no
+XLOC_000087 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 LOWDATA 0 0 0 0 0 1 no
diff -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff test-data/cuffdiff_out7.txt
--- a/test-data/cuffdiff_out7.txt
+++ b/test-data/cuffdiff_out7.txt
@@ -1,15 +1,15 @@
tracking_id class_code nearest_ref_id gene_id gene_short_name tss_id locus length coverage q1_FPKM q1_conf_lo q1_conf_hi q1_status q2_FPKM q2_conf_lo q2_conf_hi q2_status
-TSS1 - - XLOC_000001 Xkr4 TSS1 chr1:3204754-3204833 - - 0 0 0 OK 8.3103e+06 0 2.00628e+07 OK
-TSS10 - - XLOC_000008 - TSS10 chr1:3190858-3191434 - - 474092 138279 809906 OK 369273 113039 625507 OK
-TSS11 - - XLOC_000009 - TSS11 chr1:3191512-3192077 - - 502845 149756 855934 OK 739818 487934 991702 OK
-TSS13 - - XLOC_000010 - TSS13 chr1:3192250-3192336 - - 3.994e+06 0 1.1982e+07 OK 2.93812e+06 0 8.81435e+06 OK
-TSS14 - - XLOC_000011 - TSS14 chr1:3192441-3192494 - - 0 0 0 OK 8.52143e+07 0 1.83611e+08 OK
-TSS15 - - XLOC_000012 - TSS15 chr1:3192550-3192629 - - 0 0 0 OK 4.15515e+06 0 1.24654e+07 OK
+TSS1 - - XLOC_000001 Xkr4 TSS1 chr1:3204754-3204833 - - 0 0 0 OK 5.42247e+06 0 1.83844e+07 OK
+TSS10 - - XLOC_000008 - TSS10 chr1:3190858-3191434 - - 227564 0 483427 OK 240951 0 505030 OK
+TSS11 - - XLOC_000009 - TSS11 chr1:3191512-3192077 - - 241366 0 509259 OK 482731 109420 856042 OK
+TSS13 - - XLOC_000010 - TSS13 chr1:3192250-3192336 - - 1.91712e+06 0 7.66198e+06 OK 1.91712e+06 0 7.66198e+06 OK
+TSS14 - - XLOC_000011 - TSS14 chr1:3192441-3192494 - - 0 0 0 OK 5.56023e+07 0 1.86077e+08 OK
+TSS15 - - XLOC_000012 - TSS15 chr1:3192550-3192629 - - 0 0 0 OK 2.71123e+06 0 1.08357e+07 OK
TSS16 - - XLOC_000013 - TSS16 chr1:3192649-3192676 - - 0 0 0 OK 0 0 0 OK
TSS17 - - XLOC_000014 - TSS17 chr1:3192731-3192811 - - 0 0 0 OK 0 0 0 OK
-TSS18 - - XLOC_000015 - TSS18 chr1:3192940-3193042 - - 0 0 0 OK 6.02976e+06 0 1.34147e+07 OK
-TSS19 - - XLOC_000016 - TSS19 chr1:3194185-3194226 - - 0 0 0 OK 2.1403e+08 0 6.42089e+08 OK
-TSS2 - - XLOC_000002 - TSS2 chr1:3111449-3111490 - - 0 0 0 OK 2.1403e+08 0 6.42089e+08 OK
+TSS18 - - XLOC_000015 - TSS18 chr1:3192940-3193042 - - 0 0 0 OK 3.93442e+06 0 1.25021e+07 OK
+TSS19 - - XLOC_000016 - TSS19 chr1:3194185-3194226 - - 0 0 0 OK 1.39654e+08 0 5.58144e+08 OK
+TSS2 - - XLOC_000002 - TSS2 chr1:3111449-3111490 - - 0 0 0 OK 1.39654e+08 0 5.58144e+08 OK
TSS20 - - XLOC_000017 - TSS20 chr1:3194302-3194329 - - 0 0 0 OK 0 0 0 OK
TSS21 - - XLOC_000018 - TSS21 chr1:3194706-3194733 - - 0 0 0 OK 0 0 0 OK
TSS22 - - XLOC_000019 - TSS22 chr1:3195083-3195110 - - 0 0 0 OK 0 0 0 OK
@@ -18,62 +18,62 @@
TSS25 - - XLOC_000022 - TSS25 chr1:3197246-3197273 - - 0 0 0 OK 0 0 0 OK
TSS26 - - XLOC_000023 - TSS26 chr1:3197346-3197373 - - 0 0 0 OK 0 0 0 OK
TSS27 - - XLOC_000024 - TSS27 chr1:3197425-3197452 - - 0 0 0 OK 0 0 0 OK
-TSS28 - - XLOC_000025 - TSS28 chr1:3200022-3200191 - - 959058 0 2.06648e+06 OK 705514 0 1.52017e+06 OK
+TSS28 - - XLOC_000025 - TSS28 chr1:3200022-3200191 - - 460348 0 1.54058e+06 OK 460348 0 1.54058e+06 OK
TSS29 - - XLOC_000026 - TSS29 chr1:3200325-3200352 - - 0 0 0 OK 0 0 0 OK
TSS3 - - XLOC_000003 - TSS3 chr1:3111545-3111576 - - 0 0 0 OK 0 0 0 OK
TSS30 - - XLOC_000027 - TSS30 chr1:3200430-3200457 - - 0 0 0 OK 0 0 0 OK
TSS31 - - XLOC_000028 - TSS31 chr1:3201007-3201039 - - 0 0 0 OK 0 0 0 OK
-TSS32 - - XLOC_000029 - TSS32 chr1:3201077-3201481 - - 77513.9 0 167019 OK 285108 21736.5 548480 OK
-TSS33 - - XLOC_000030 - TSS33 chr1:3201596-3201666 - - 1.89853e+07 0 4.58345e+07 OK 0 0 0 OK
+TSS32 - - XLOC_000029 - TSS32 chr1:3201077-3201481 - - 37206.6 0 124514 OK 186033 0 476912 OK
+TSS33 - - XLOC_000030 - TSS33 chr1:3201596-3201666 - - 9.11292e+06 0 3.08965e+07 OK 0 0 0 OK
TSS34 - - XLOC_000031 - TSS34 chr1:3201672-3201699 - - 0 0 0 OK 0 0 0 OK
-TSS35 - - XLOC_000032 - TSS35 chr1:3201725-3201809 - - 1.75659e+07 0 3.90796e+07 OK 0 0 0 OK
+TSS35 - - XLOC_000032 - TSS35 chr1:3201725-3201809 - - 8.43162e+06 0 2.67925e+07 OK 0 0 0 OK
TSS36 - - XLOC_000033 Xkr4 TSS36 chr1:3211521-3211561 - - 0 0 0 OK 0 0 0 OK
-TSS37 - - XLOC_000034 Xkr4 TSS37 chr1:3212213-3212292 - - 0 0 0 OK 8.3103e+06 0 2.00628e+07 OK
-TSS38 - - XLOC_000035 Xkr4 TSS38 chr1:3212367-3212439 - - 0 0 0 OK 2.4671e+07 0 5.48867e+07 OK
-TSS39 - - XLOC_000036 Xkr4 TSS39 chr1:3212717-3212801 - - 4.39147e+06 0 1.31744e+07 OK 0 0 0 OK
+TSS37 - - XLOC_000034 Xkr4 TSS37 chr1:3212213-3212292 - - 0 0 0 OK 5.42247e+06 0 1.83844e+07 OK
+TSS38 - - XLOC_000035 Xkr4 TSS38 chr1:3212367-3212439 - - 0 0 0 OK 1.60978e+07 0 5.11527e+07 OK
+TSS39 - - XLOC_000036 Xkr4 TSS39 chr1:3212717-3212801 - - 2.10791e+06 0 8.42447e+06 OK 0 0 0 OK
TSS4 - - XLOC_000004 - TSS4 chr1:3174765-3174792 - - 0 0 0 OK 0 0 0 OK
-TSS40 - - XLOC_000037 Xkr4 TSS40 chr1:3213095-3213242 - - 8.89174e+06 0 2.05036e+07 OK 1.82908e+06 0 5.48723e+06 OK
+TSS40 - - XLOC_000037 Xkr4 TSS40 chr1:3213095-3213242 - - 2.84535e+06 0 1.07397e+07 OK 1.19347e+06 0 5.96736e+06 OK
TSS41 - - XLOC_000038 Xkr4 TSS41 chr1:3240606-3240633 - - 0 0 0 OK 0 0 0 OK
TSS42 - - XLOC_000039 Xkr4 TSS42 chr1:3242479-3242512 - - 0 0 0 OK 0 0 0 OK
-TSS43 - - XLOC_000040 Xkr4 TSS43 chr1:3242633-3242923 - - 56312.4 0 168937 OK 372827 0 761430 OK
+TSS43 - - XLOC_000040 Xkr4 TSS43 chr1:3242633-3242923 - - 27029.9 0 108028 OK 243269 0 681799 OK
TSS44 - - XLOC_000041 Xkr4 TSS44 chr1:3242924-3243005 - - 0 0 0 OK 0 0 0 OK
-TSS45 - - XLOC_000042 Xkr4 TSS45 chr1:3243018-3243079 - - 0 0 0 OK 2.66226e+07 0 6.42725e+07 OK
-TSS46 - - XLOC_000043 Xkr4 TSS46 chr1:3243108-3243154 - - 9.99919e+07 0 2.99976e+08 OK 0 0 0 OK
-TSS47 - - XLOC_000044 Xkr4 TSS47 chr1:3243347-3243401 - - 0 0 0 OK 5.0951e+07 0 1.23007e+08 OK
+TSS45 - - XLOC_000042 Xkr4 TSS45 chr1:3243018-3243079 - - 0 0 0 OK 1.73712e+07 0 5.88955e+07 OK
+TSS46 - - XLOC_000043 Xkr4 TSS46 chr1:3243108-3243154 - - 4.79961e+07 0 1.91822e+08 OK 0 0 0 OK
+TSS47 - - XLOC_000044 Xkr4 TSS47 chr1:3243347-3243401 - - 0 0 0 OK 3.32455e+07 0 1.12716e+08 OK
TSS48 - - XLOC_000045 Xkr4 TSS48 chr1:3254079-3254106 - - 0 0 0 OK 0 0 0 OK
-TSS49 - - XLOC_000046 Xkr4 TSS49 chr1:3256974-3257011 - - 0 0 0 OK 2.06814e+09 0 4.99293e+09 OK
+TSS49 - - XLOC_000046 Xkr4 TSS49 chr1:3256974-3257011 - - 0 0 0 OK 1.34946e+09 0 4.57522e+09 OK
TSS5 - - XLOC_000005 - TSS5 chr1:3187401-3187428 - - 0 0 0 OK 0 0 0 OK
TSS50 - - XLOC_000047 Xkr4 TSS50 chr1:3277155-3277182 - - 0 0 0 OK 0 0 0 OK
TSS51 - - XLOC_000048 Xkr4 TSS51 chr1:3277190-3277218 - - 0 0 0 OK 0 0 0 OK
-TSS52 - - XLOC_000049 Xkr4 TSS52 chr1:3277913-3278390 - - 265614 16793 514436 OK 41870.3 0 90217.9 OK
+TSS52 - - XLOC_000049 Xkr4 TSS52 chr1:3277913-3278390 - - 127495 0 331348 OK 27320.3 0 91429.2 OK
TSS54 - - XLOC_000050 Xkr4 TSS54 chr1:3280117-3280144 - - 0 0 0 OK 0 0 0 OK
TSS55 - - XLOC_000051 Xkr4 TSS55 chr1:3280498-3280525 - - 0 0 0 OK 0 0 0 OK
-TSS56 - - XLOC_000052 Xkr4 TSS56 chr1:3280686-3280741 - - 0 0 0 OK 2.29576e+07 0 6.88728e+07 OK
+TSS56 - - XLOC_000052 Xkr4 TSS56 chr1:3280686-3280741 - - 0 0 0 OK 1.49798e+07 0 5.98686e+07 OK
TSS57 - - XLOC_000053 Xkr4 TSS57 chr1:3282504-3282531 - - 0 0 0 OK 0 0 0 OK
TSS58 - - XLOC_000054 Xkr4 TSS58 chr1:3282650-3282677 - - 0 0 0 OK 0 0 0 OK
TSS59 - - XLOC_000055 Xkr4 TSS59 chr1:3282760-3282832 - - 0 0 0 OK 0 0 0 OK
TSS6 - - XLOC_000006 - TSS6 chr1:3188521-3188548 - - 0 0 0 OK 0 0 0 OK
TSS60 - - XLOC_000056 Xkr4 TSS60 chr1:3284966-3284993 - - 0 0 0 OK 0 0 0 OK
-TSS61 - - XLOC_000057 Xkr4 TSS61 chr1:3290488-3290553 - - 0 0 0 OK 9.79535e+06 0 2.9386e+07 OK
-TSS62 - - XLOC_000058 Xkr4 TSS62 chr1:3290798-3290859 - - 1.8095e+07 0 5.4285e+07 OK 0 0 0 OK
-TSS63 - - XLOC_000059 Xkr4 TSS63 chr1:3290919-3291273 - - 342218 0 691214 OK 75524 0 162732 OK
-TSS65 - - XLOC_000060 Xkr4 TSS65 chr1:3299443-3299664 - - 937403 0 1.99795e+06 OK 137917 0 413751 OK
+TSS61 - - XLOC_000057 Xkr4 TSS61 chr1:3290488-3290553 - - 0 0 0 OK 6.39146e+06 0 2.55442e+07 OK
+TSS62 - - XLOC_000058 Xkr4 TSS62 chr1:3290798-3290859 - - 8.68561e+06 0 3.4713e+07 OK 0 0 0 OK
+TSS63 - - XLOC_000059 Xkr4 TSS63 chr1:3290919-3291273 - - 164265 0 453103 OK 49279.4 0 164917 OK
+TSS65 - - XLOC_000060 Xkr4 TSS65 chr1:3299443-3299664 - - 449954 0 1.56567e+06 OK 89990.7 0 449954 OK
TSS66 - - XLOC_000060 Xkr4 TSS66 chr1:3299443-3299664 - - 0 0 0 OK 0 0 0 OK
TSS67 - - XLOC_000061 Xkr4 TSS67 chr1:3299691-3299733 - - 0 0 0 OK 0 0 0 OK
TSS68 - - XLOC_000062 Xkr4 TSS68 chr1:3300051-3300078 - - 0 0 0 OK 0 0 0 OK
TSS69 - - XLOC_000063 Xkr4 TSS69 chr1:3307748-3307775 - - 0 0 0 OK 0 0 0 OK
-TSS7 - - XLOC_000007 - TSS7 chr1:3189810-3190789 - - 415851 231920 599782 OK 458870 363705 554035 OK
+TSS7 - - XLOC_000007 - TSS7 chr1:3189810-3190789 - - 199608 33901.5 365315 OK 299412 183619 415206 OK
TSS70 - - XLOC_000064 Xkr4 TSS70 chr1:3318620-3318647 - - 0 0 0 OK 0 0 0 OK
TSS71 - - XLOC_000065 Xkr4 TSS71 chr1:3318999-3319051 - - 0 0 0 OK 0 0 0 OK
TSS72 - - XLOC_000066 Xkr4 TSS72 chr1:3330527-3330554 - - 0 0 0 OK 0 0 0 OK
-TSS73 - - XLOC_000067 Xkr4 TSS73 chr1:3351240-3351311 - - 8.91489e+06 0 2.67447e+07 OK 0 0 0 OK
-TSS74 - - XLOC_000068 Xkr4 TSS74 chr1:3355887-3356119 - - 585828 0 1.30332e+06 OK 0 0 0 OK
-TSS75 - - XLOC_000069 Xkr4 TSS75 chr1:3356180-3356225 - - 1.19208e+08 0 3.57623e+08 OK 0 0 0 OK
-TSS76 - - XLOC_000070 Xkr4 TSS76 chr1:3363076-3363176 - - 4.42166e+06 0 1.06748e+07 OK 0 0 0 OK
+TSS73 - - XLOC_000067 Xkr4 TSS73 chr1:3351240-3351311 - - 4.27915e+06 0 1.71021e+07 OK 0 0 0 OK
+TSS74 - - XLOC_000068 Xkr4 TSS74 chr1:3355887-3356119 - - 281197 0 1.06014e+06 OK 0 0 0 OK
+TSS75 - - XLOC_000069 Xkr4 TSS75 chr1:3356180-3356225 - - 5.72196e+07 0 2.28684e+08 OK 0 0 0 OK
+TSS76 - - XLOC_000070 Xkr4 TSS76 chr1:3363076-3363176 - - 2.1224e+06 0 7.19579e+06 OK 0 0 0 OK
TSS77 - - XLOC_000071 Xkr4 TSS77 chr1:3363214-3363278 - - 0 0 0 OK 0 0 0 OK
-TSS78 - - XLOC_000072 Xkr4 TSS78 chr1:3363387-3363446 - - 6.42536e+07 0 1.38447e+08 OK 0 0 0 OK
+TSS78 - - XLOC_000072 Xkr4 TSS78 chr1:3363387-3363446 - - 3.08417e+07 0 1.03214e+08 OK 0 0 0 OK
TSS79 - - XLOC_000073 Xkr4 TSS79 chr1:3363753-3363849 - - 0 0 0 OK 0 0 0 OK
-TSS80 - - XLOC_000074 Xkr4 TSS80 chr1:3364871-3364919 - - 7.29939e+07 0 2.18982e+08 OK 0 0 0 OK
+TSS80 - - XLOC_000074 Xkr4 TSS80 chr1:3364871-3364919 - - 3.50371e+07 0 1.40029e+08 OK 0 0 0 OK
TSS81 - - XLOC_000075 Xkr4 TSS81 chr1:3367135-3367162 - - 0 0 0 OK 0 0 0 OK
TSS82 - - XLOC_000076 Xkr4 TSS82 chr1:3367210-3367237 - - 0 0 0 OK 0 0 0 OK
TSS83 - - XLOC_000077 Xkr4 TSS83 chr1:3367333-3367382 - - 0 0 0 OK 0 0 0 OK
diff -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff test-data/cuffdiff_out9.txt
--- a/test-data/cuffdiff_out9.txt
+++ b/test-data/cuffdiff_out9.txt
@@ -1,89 +1,89 @@
test_id gene_id gene locus sample_1 sample_2 status value_1 value_2 sqrt(JS) test_stat p_value q_value significant
-TSS1 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS10 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS11 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS13 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS14 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS15 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS16 XLOC_000013 - chr1:3192649-3192676 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS17 XLOC_000014 - chr1:3192731-3192811 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS18 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS19 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS2 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS20 XLOC_000017 - chr1:3194302-3194329 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS21 XLOC_000018 - chr1:3194706-3194733 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS22 XLOC_000019 - chr1:3195083-3195110 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS23 XLOC_000020 - chr1:3195450-3195477 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS24 XLOC_000021 - chr1:3197089-3197116 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS25 XLOC_000022 - chr1:3197246-3197273 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS26 XLOC_000023 - chr1:3197346-3197373 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS27 XLOC_000024 - chr1:3197425-3197452 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS28 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS29 XLOC_000026 - chr1:3200325-3200352 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS3 XLOC_000003 - chr1:3111545-3111576 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS30 XLOC_000027 - chr1:3200430-3200457 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS31 XLOC_000028 - chr1:3201007-3201039 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS32 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS33 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS34 XLOC_000031 - chr1:3201672-3201699 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS35 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS36 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS37 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS38 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS39 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS4 XLOC_000004 - chr1:3174765-3174792 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS40 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 OK 0 0 0.249945 0.143447 0.135175 0.135175 no
-TSS41 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS42 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS43 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS44 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS45 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS46 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS47 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS48 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS49 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS5 XLOC_000005 - chr1:3187401-3187428 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS50 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS51 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS52 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS54 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS55 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS56 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS57 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS58 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS59 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS6 XLOC_000006 - chr1:3188521-3188548 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS60 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS61 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS62 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS63 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS65 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS66 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS67 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS68 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS69 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS7 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS70 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS71 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS72 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS73 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS74 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS75 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS76 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS77 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS78 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS79 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS80 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS81 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS82 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS83 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS84 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS85 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS86 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS87 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS88 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS89 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS90 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS91 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS92 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 NOTEST 0 0 0 0 0 1 no
-TSS93 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 NOTEST 0 0 0 0 0 1 no
+TSS1 XLOC_000001 Xkr4 chr1:3204754-3204833 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS10 XLOC_000008 - chr1:3190858-3191434 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS11 XLOC_000009 - chr1:3191512-3192077 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS13 XLOC_000010 - chr1:3192250-3192336 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS14 XLOC_000011 - chr1:3192441-3192494 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS15 XLOC_000012 - chr1:3192550-3192629 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS16 XLOC_000013 - chr1:3192649-3192676 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS17 XLOC_000014 - chr1:3192731-3192811 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS18 XLOC_000015 - chr1:3192940-3193042 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS19 XLOC_000016 - chr1:3194185-3194226 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS2 XLOC_000002 - chr1:3111449-3111490 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS20 XLOC_000017 - chr1:3194302-3194329 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS21 XLOC_000018 - chr1:3194706-3194733 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS22 XLOC_000019 - chr1:3195083-3195110 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS23 XLOC_000020 - chr1:3195450-3195477 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS24 XLOC_000021 - chr1:3197089-3197116 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS25 XLOC_000022 - chr1:3197246-3197273 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS26 XLOC_000023 - chr1:3197346-3197373 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS27 XLOC_000024 - chr1:3197425-3197452 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS28 XLOC_000025 - chr1:3200022-3200191 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS29 XLOC_000026 - chr1:3200325-3200352 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS3 XLOC_000003 - chr1:3111545-3111576 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS30 XLOC_000027 - chr1:3200430-3200457 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS31 XLOC_000028 - chr1:3201007-3201039 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS32 XLOC_000029 - chr1:3201077-3201481 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS33 XLOC_000030 - chr1:3201596-3201666 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS34 XLOC_000031 - chr1:3201672-3201699 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS35 XLOC_000032 - chr1:3201725-3201809 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS36 XLOC_000033 Xkr4 chr1:3211521-3211561 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS37 XLOC_000034 Xkr4 chr1:3212213-3212292 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS38 XLOC_000035 Xkr4 chr1:3212367-3212439 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS39 XLOC_000036 Xkr4 chr1:3212717-3212801 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS4 XLOC_000004 - chr1:3174765-3174792 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS40 XLOC_000037 Xkr4 chr1:3213095-3213242 q1 q2 NOTEST 0 0 0.249947 0 0.557805 1 no
+TSS41 XLOC_000038 Xkr4 chr1:3240606-3240633 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS42 XLOC_000039 Xkr4 chr1:3242479-3242512 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS43 XLOC_000040 Xkr4 chr1:3242633-3242923 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS44 XLOC_000041 Xkr4 chr1:3242924-3243005 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS45 XLOC_000042 Xkr4 chr1:3243018-3243079 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS46 XLOC_000043 Xkr4 chr1:3243108-3243154 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS47 XLOC_000044 Xkr4 chr1:3243347-3243401 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS48 XLOC_000045 Xkr4 chr1:3254079-3254106 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS49 XLOC_000046 Xkr4 chr1:3256974-3257011 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS5 XLOC_000005 - chr1:3187401-3187428 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS50 XLOC_000047 Xkr4 chr1:3277155-3277182 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS51 XLOC_000048 Xkr4 chr1:3277190-3277218 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS52 XLOC_000049 Xkr4 chr1:3277913-3278390 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS54 XLOC_000050 Xkr4 chr1:3280117-3280144 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS55 XLOC_000051 Xkr4 chr1:3280498-3280525 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS56 XLOC_000052 Xkr4 chr1:3280686-3280741 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS57 XLOC_000053 Xkr4 chr1:3282504-3282531 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS58 XLOC_000054 Xkr4 chr1:3282650-3282677 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS59 XLOC_000055 Xkr4 chr1:3282760-3282832 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS6 XLOC_000006 - chr1:3188521-3188548 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS60 XLOC_000056 Xkr4 chr1:3284966-3284993 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS61 XLOC_000057 Xkr4 chr1:3290488-3290553 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS62 XLOC_000058 Xkr4 chr1:3290798-3290859 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS63 XLOC_000059 Xkr4 chr1:3290919-3291273 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS65 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS66 XLOC_000060 Xkr4 chr1:3299443-3299664 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS67 XLOC_000061 Xkr4 chr1:3299691-3299733 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS68 XLOC_000062 Xkr4 chr1:3300051-3300078 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS69 XLOC_000063 Xkr4 chr1:3307748-3307775 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS7 XLOC_000007 - chr1:3189810-3190789 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS70 XLOC_000064 Xkr4 chr1:3318620-3318647 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS71 XLOC_000065 Xkr4 chr1:3318999-3319051 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS72 XLOC_000066 Xkr4 chr1:3330527-3330554 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS73 XLOC_000067 Xkr4 chr1:3351240-3351311 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS74 XLOC_000068 Xkr4 chr1:3355887-3356119 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS75 XLOC_000069 Xkr4 chr1:3356180-3356225 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS76 XLOC_000070 Xkr4 chr1:3363076-3363176 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS77 XLOC_000071 Xkr4 chr1:3363214-3363278 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS78 XLOC_000072 Xkr4 chr1:3363387-3363446 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS79 XLOC_000073 Xkr4 chr1:3363753-3363849 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS80 XLOC_000074 Xkr4 chr1:3364871-3364919 q1 q2 NOTEST 0 0 0 0 1 1 no
+TSS81 XLOC_000075 Xkr4 chr1:3367135-3367162 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS82 XLOC_000076 Xkr4 chr1:3367210-3367237 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS83 XLOC_000077 Xkr4 chr1:3367333-3367382 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS84 XLOC_000078 Xkr4 chr1:3369580-3369607 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS85 XLOC_000079 Xkr4 chr1:3375001-3375028 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS86 XLOC_000080 Xkr4 chr1:3377211-3377262 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS87 XLOC_000081 Xkr4 chr1:3379888-3379915 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS88 XLOC_000082 Xkr4 chr1:3386739-3386836 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS89 XLOC_000083 Xkr4 chr1:3391325-3391352 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS90 XLOC_000084 Xkr4 chr1:3435841-3435880 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS91 XLOC_000085 Xkr4 chr1:3447761-3447788 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS92 XLOC_000086 Xkr4 chr1:3450906-3450965 q1 q2 LOWDATA 0 0 0 0 0 1 no
+TSS93 XLOC_000087 Xkr4 chr1:3451051-3451109 q1 q2 LOWDATA 0 0 0 0 0 1 no
diff -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff tools/ngs_rna/cuffdiff_wrapper.py
--- a/tools/ngs_rna/cuffdiff_wrapper.py
+++ b/tools/ngs_rna/cuffdiff_wrapper.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+# Wrapper supports Cuffdiff versions v1.3.0-v2.0
+
import optparse, os, shutil, subprocess, sys, tempfile
def group_callback( option, op_str, value, parser ):
@@ -59,6 +61,7 @@
where each end is 50bp, you should set -r to be 200. The default is 45bp.')
parser.add_option( '-c', '--min-alignment-count', dest='min_alignment_count', help='The minimum number of alignments in a locus for needed to conduct significance testing on changes in that locus observed between samples. If no testing is performed, changes in the locus are deemed not signficant, and the locus\' observed changes don\'t contribute to correction for multiple testing. The default is 1,000 fragment alignments (up to 2,000 paired reads).' )
parser.add_option( '--FDR', dest='FDR', help='The allowed false discovery rate. The default is 0.05.' )
+ parser.add_option( '-u', '--multi-read-correct', dest='multi_read_correct', action="store_true", help='Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome')
# Advanced Options:
parser.add_option( '--num-importance-samples', dest='num_importance_samples', help='Sets the number of importance samples generated for each locus during abundance estimation. Default: 1000' )
@@ -153,6 +156,8 @@
cmd += ( " -c %i" % int ( options.min_alignment_count ) )
if options.FDR:
cmd += ( " --FDR %f" % float( options.FDR ) )
+ if options.multi_read_correct:
+ cmd += ( " -u" )
if options.num_importance_samples:
cmd += ( " --num-importance-samples %i" % int ( options.num_importance_samples ) )
if options.max_mle_iterations:
diff -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff tools/ngs_rna/cuffdiff_wrapper.xml
--- a/tools/ngs_rna/cuffdiff_wrapper.xml
+++ b/tools/ngs_rna/cuffdiff_wrapper.xml
@@ -1,5 +1,5 @@
<tool id="cuffdiff" name="Cuffdiff" version="0.0.5">
- <!-- Wrapper supports Cuffdiff versions v1.0.0-v1.3.0 -->
+ <!-- Wrapper supports Cuffdiff versions v1.3.0-v2.0 --><description>find significant changes in transcript expression, splicing, and promoter use</description><requirements><requirement type="package">cufflinks</requirement>
@@ -33,7 +33,11 @@
-N
#end if
-
+ ## Multi-read correct?
+ #if str($multiread_correct) == "Yes":
+ -u
+ #end if
+
## Bias correction?
#if $bias_correction.do_bias_correction == "Yes":
-b
@@ -89,11 +93,19 @@
</conditional><param name="fdr" type="float" value="0.05" label="False Discovery Rate" help="The allowed false discovery rate."/>
+
<param name="min_alignment_count" type="integer" value="10" label="Min Alignment Count" help="The minimum number of alignments in a locus for needed to conduct significance testing on changes in that locus observed between samples."/>
+
<param name="do_normalization" type="select" label="Perform quartile normalization" help="Removes top 25% of genes from FPKM denominator to improve accuracy of differential expression calls for low abundance transcripts."><option value="No">No</option><option value="Yes">Yes</option></param>
+
+ <param name="multiread_correct" type="select" label="Use multi-read correct" help="Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome.">
+ <option value="No" selected="true">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+
<conditional name="bias_correction"><param name="do_bias_correction" type="select" label="Perform Bias Correction" help="Bias detection and correction can significantly improve accuracy of transcript abundance estimates."><option value="No">No</option>
@@ -113,6 +125,7 @@
</when><when value="No"></when></conditional>
+
<conditional name="additional"><param name="sAdditional" type="select" label="Set Additional Parameters? (not recommended)"><option value="No">No</option>
@@ -154,6 +167,7 @@
<param name="min_alignment_count" value="0" /><param name="do_bias_correction" value="No" /><param name="do_normalization" value="No" />
+ <param name="multiread_correct" value="No"/><param name="sAdditional" value="No"/><!--
Line diffs are needed because cuffdiff does not produce deterministic output.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Bump version support for Cuffcompare, Cuffmerge to v2.0 and increase lines_diff to prevent Cuffmerge test from failing due to non-deterministic output.
by Bitbucket 26 Sep '12
by Bitbucket 26 Sep '12
26 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/199767a1714b/
changeset: 199767a1714b
user: jgoecks
date: 2012-09-26 16:30:59
summary: Bump version support for Cuffcompare, Cuffmerge to v2.0 and increase lines_diff to prevent Cuffmerge test from failing due to non-deterministic output.
affected #: 4 files
diff -r cfd6428269c88c4690d644929969e852af672f45 -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 tools/ngs_rna/cuffcompare_wrapper.py
--- a/tools/ngs_rna/cuffcompare_wrapper.py
+++ b/tools/ngs_rna/cuffcompare_wrapper.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+# Supports Cuffcompare versions v1.3.0 and newer.
+
import optparse, os, shutil, subprocess, sys, tempfile
def stop_err( msg ):
diff -r cfd6428269c88c4690d644929969e852af672f45 -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 tools/ngs_rna/cuffcompare_wrapper.xml
--- a/tools/ngs_rna/cuffcompare_wrapper.xml
+++ b/tools/ngs_rna/cuffcompare_wrapper.xml
@@ -1,5 +1,5 @@
<tool id="cuffcompare" name="Cuffcompare" version="0.0.5">
- <!-- Wrapper supports Cuffcompare versions v1.0.0-v1.3.0 -->
+ <!-- Wrapper supports Cuffcompare versions v1.3.0 and newer --><description>compare assembled transcripts to a reference annotation and track Cufflinks transcripts across multiple experiments</description><requirements><requirement type="package">cufflinks</requirement>
diff -r cfd6428269c88c4690d644929969e852af672f45 -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 tools/ngs_rna/cuffmerge_wrapper.py
--- a/tools/ngs_rna/cuffmerge_wrapper.py
+++ b/tools/ngs_rna/cuffmerge_wrapper.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+# Supports Cuffmerge versions 1.3 and newer.
+
import optparse, os, shutil, subprocess, sys, tempfile
def stop_err( msg ):
diff -r cfd6428269c88c4690d644929969e852af672f45 -r 199767a1714b27a9a5c3f2376ad0133a70cd7c51 tools/ngs_rna/cuffmerge_wrapper.xml
--- a/tools/ngs_rna/cuffmerge_wrapper.xml
+++ b/tools/ngs_rna/cuffmerge_wrapper.xml
@@ -1,5 +1,5 @@
<tool id="cuffmerge" name="Cuffmerge" version="0.0.5">
- <!-- Wrapper supports Cuffmerge version v1.0.0 -->
+ <!-- Wrapper supports Cuffmerge versions 1.3 and newer --><description>merge together several Cufflinks assemblies</description><requirements><requirement type="package">cufflinks</requirement>
@@ -88,7 +88,7 @@
<param name="reference_annotation" value="cuffcompare_in3.gtf" ftype="gtf"/><param name="use_seq_data" value="No"/><!-- oId assignment differ/are non-deterministic -->
- <output name="merged_transcripts" file="cuffmerge_out1.gtf" lines_diff="8"/>
+ <output name="merged_transcripts" file="cuffmerge_out1.gtf" lines_diff="50"/></test></tests>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Cufflinks wrapper: add support for v2.0, add multiread correction parameter, and remove unused parameters.
by Bitbucket 26 Sep '12
by Bitbucket 26 Sep '12
26 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/cfd6428269c8/
changeset: cfd6428269c8
user: jgoecks
date: 2012-09-26 15:35:18
summary: Cufflinks wrapper: add support for v2.0, add multiread correction parameter, and remove unused parameters.
affected #: 2 files
diff -r 20144ac9ffa7d15a9738cee2a5c8cb2b4cf1c401 -r cfd6428269c88c4690d644929969e852af672f45 tools/ngs_rna/cufflinks_wrapper.py
--- a/tools/ngs_rna/cufflinks_wrapper.py
+++ b/tools/ngs_rna/cufflinks_wrapper.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+# Supports Cufflinks versions 1.3 and newer.
+
import optparse, os, shutil, subprocess, sys, tempfile
from galaxy import eggs
from galaxy.datatypes.util.gff_util import parse_gff_attributes, gff_attributes_to_str
@@ -36,6 +38,7 @@
where each end is 50bp, you should set -r to be 200. The default is 45bp.')
parser.add_option( '-G', '--GTF', dest='GTF', help='Tells Cufflinks to use the supplied reference annotation to estimate isoform expression. It will not assemble novel transcripts, and the program will ignore alignments not structurally compatible with any reference transcript.' )
parser.add_option( '-g', '--GTF-guide', dest='GTFguide', help='use reference transcript annotation to guide assembly' )
+ parser.add_option( '-u', '--multi-read-correct', dest='multi_read_correct', action="store_true", help='Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome')
# Normalization options.
parser.add_option( "-N", "--quartile-normalization", dest="do_normalization", action="store_true" )
@@ -116,7 +119,9 @@
if options.GTF:
cmd += ( " -G %s" % options.GTF )
if options.GTFguide:
- cmd += ( " -g %s" % options.GTFguide )
+ cmd += ( " -g %s" % options.GTFguide )
+ if options.multi_read_correct:
+ cmd += ( " -u" )
if options.num_importance_samples:
cmd += ( " --num-importance-samples %i" % int ( options.num_importance_samples ) )
if options.max_mle_iterations:
@@ -157,7 +162,7 @@
total_map_mass = -1
tmp_stderr = open( tmp_name, 'r' )
for line in tmp_stderr:
- if line.lower().find( "total map mass" ) >= 0 or line.lower().find( "upper quartile" ) >= 0:
+ if line.lower().find( "map mass" ) >= 0 or line.lower().find( "upper quartile" ) >= 0:
total_map_mass = float( line.split(":")[1].strip() )
break
tmp_stderr.close()
diff -r 20144ac9ffa7d15a9738cee2a5c8cb2b4cf1c401 -r cfd6428269c88c4690d644929969e852af672f45 tools/ngs_rna/cufflinks_wrapper.xml
--- a/tools/ngs_rna/cufflinks_wrapper.xml
+++ b/tools/ngs_rna/cufflinks_wrapper.xml
@@ -1,5 +1,5 @@
<tool id="cufflinks" name="Cufflinks" version="0.0.5">
- <!-- Wrapper supports Cufflinks versions v1.0.0-v1.3.0 -->
+ <!-- Wrapper supports Cufflinks versions v1.3.0 and newer --><description>transcript assembly and FPKM (RPKM) estimates for RNA-Seq data</description><requirements><requirement type="package">cufflinks</requirement>
@@ -20,12 +20,6 @@
#if $reference_annotation.use_ref == "Use reference annotation guide":
-g $reference_annotation.reference_annotation_guide_file
#end if
-
- ## Set paired-end parameters?
- #if $singlePaired.sPaired == "Yes":
- -m $singlePaired.mean_inner_distance
- -s $singlePaired.inner_distance_std_dev
- #end if
## Normalization?
#if str($do_normalization) == "Yes":
@@ -34,7 +28,7 @@
## Bias correction?
#if $bias_correction.do_bias_correction == "Yes":
- -b
+ -b
#if $bias_correction.seq_source.index_source == "history":
--ref_file=$bias_correction.seq_source.ref_file
#else:
@@ -44,6 +38,11 @@
--index_dir=${GALAXY_DATA_INDEX_DIR}
#end if
+ ## Multi-read correct?
+ #if str($multiread_correct) == "Yes":
+ -u
+ #end if
+
## Include global model if available.
#if $global_model:
--global_model=$global_model
@@ -55,12 +54,12 @@
<param name="min_isoform_fraction" type="float" value="0.10" min="0" max="1" label="Min Isoform Fraction" help=""/><param name="pre_mrna_fraction" type="float" value="0.15" min="0" max="1" label="Pre MRNA Fraction" help=""/><param name="do_normalization" type="select" label="Perform quartile normalization" help="Removes top 25% of genes from FPKM denominator to improve accuracy of differential expression calls for low abundance transcripts.">
- <option value="No">No</option>
+ <option value="No" selected="true">No</option><option value="Yes">Yes</option></param><conditional name="reference_annotation"><param name="use_ref" type="select" label="Use Reference Annotation">
- <option value="No">No</option>
+ <option value="No" selected="true">No</option><option value="Use reference annotation">Use reference annotation</option><option value="Use reference annotation guide">Use reference annotation as guide</option></param>
@@ -74,13 +73,13 @@
</conditional><conditional name="bias_correction"><param name="do_bias_correction" type="select" label="Perform Bias Correction" help="Bias detection and correction can significantly improve accuracy of transcript abundance estimates.">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
+ <option value="No" selected="true">No</option>
+ <option value="Yes">Yes</option></param><when value="Yes"><conditional name="seq_source"><param name="index_source" type="select" label="Reference sequence data">
- <option value="cached">Locally cached</option>
+ <option value="cached" selected="true">Locally cached</option><option value="history">History</option></param><when value="cached"></when>
@@ -91,17 +90,12 @@
</when><when value="No"></when></conditional>
- <conditional name="singlePaired">
- <param name="sPaired" type="select" label="Set Parameters for Paired-end Reads? (not recommended)">
- <option value="No">No</option>
- <option value="Yes">Yes</option>
- </param>
- <when value="No"></when>
- <when value="Yes">
- <param name="mean_inner_distance" type="integer" value="20" label="Mean Inner Distance between Mate Pairs"/>
- <param name="inner_distance_std_dev" type="integer" value="20" label="Standard Deviation for Inner Distance between Mate Pairs"/>
- </when>
- </conditional>
+
+ <param name="multiread_correct" type="select" label="Use multi-read correct" help="Tells Cufflinks to do an initial estimation procedure to more accurately weight reads mapping to multiple locations in the genome.">
+ <option value="No" selected="true">No</option>
+ <option value="Yes">Yes</option>
+ </param>
+
<param name="global_model" type="hidden_data" label="Global model (for use in Trackster)" optional="True"/></inputs>
@@ -121,7 +115,6 @@
Simple test that uses test data included with cufflinks.
--><test>
- <param name="sPaired" value="No"/><param name="input" value="cufflinks_in.bam"/><param name="max_intron_len" value="300000"/><param name="min_isoform_fraction" value="0.05"/>
@@ -129,6 +122,7 @@
<param name="use_ref" value="No"/><param name="do_normalization" value="No" /><param name="do_bias_correction" value="No"/>
+ <param name="multiread_correct" value="No"/><output name="genes_expression" format="tabular" lines_diff="2" file="cufflinks_out3.fpkm_tracking"/><output name="transcripts_expression" format="tabular" lines_diff="2" file="cufflinks_out2.fpkm_tracking"/><output name="assembled_isoforms" file="cufflinks_out1.gtf"/>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add a required import to a tool shed controller.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/20144ac9ffa7/
changeset: 20144ac9ffa7
user: greg
date: 2012-09-25 19:41:10
summary: Add a required import to a tool shed controller.
affected #: 1 file
diff -r 69f446023855cd7ed585ca6dde5ee581043e61f0 -r 20144ac9ffa7d15a9738cee2a5c8cb2b4cf1c401 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -5,7 +5,7 @@
from galaxy.tools import *
from galaxy.util.json import from_json_string, to_json_string
from galaxy.util.hash_util import *
-from galaxy.util.shed_util import check_tool_input_params, clone_repository, copy_sample_file, generate_metadata_for_changeset_revision
+from galaxy.util.shed_util import check_tool_input_params, clone_repository, concat_messages, copy_sample_file, generate_metadata_for_changeset_revision
from galaxy.util.shed_util import get_changectx_for_changeset, get_config_from_disk, get_configured_ui, get_file_context_from_ctx, get_named_tmpfile_from_ctx
from galaxy.util.shed_util import handle_sample_files_and_load_tool_from_disk, handle_sample_files_and_load_tool_from_tmp_config
from galaxy.util.shed_util import handle_sample_tool_data_table_conf_file, INITIAL_CHANGELOG_HASH, load_tool_from_config, reset_tool_data_tables
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fixes for handling sample files in tool shed repositories.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/69f446023855/
changeset: 69f446023855
user: greg
date: 2012-09-25 19:36:43
summary: Fixes for handling sample files in tool shed repositories.
affected #: 4 files
diff -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 -r 69f446023855cd7ed585ca6dde5ee581043e61f0 lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -1469,7 +1469,7 @@
error, message = handle_sample_tool_data_table_conf_file( trans.app, tool_data_table_config )
tool, valid, message2 = load_tool_from_config( trans.app, tool_config_filepath )
message = concat_messages( message, message2 )
- return tool, valid, message
+ return tool, valid, message, sample_files
def handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir ):
tool = None
message = ''
@@ -1490,7 +1490,7 @@
if manifest_ctx and ctx_file:
tool, message2 = load_tool_from_tmp_config( trans, repo, manifest_ctx, ctx_file, work_dir )
message = concat_messages( message, message2 )
- return tool, message
+ return tool, message, sample_files
def handle_sample_tool_data_table_conf_file( app, filename, persist=False ):
"""
Parse the incoming filename and add new entries to the in-memory app.tool_data_tables dictionary. If persist is True (should only occur)
diff -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 -r 69f446023855cd7ed585ca6dde5ee581043e61f0 lib/galaxy/web/controllers/admin_toolshed.py
--- a/lib/galaxy/web/controllers/admin_toolshed.py
+++ b/lib/galaxy/web/controllers/admin_toolshed.py
@@ -1010,9 +1010,8 @@
message += '<b><toolbox></b> tag that includes a <b>tool_path</b> attribute value which is a directory relative to the Galaxy installation '
message += 'directory in order to automatically install tools from a Galaxy tool shed (e.g., the file name <b>shed_tool_conf.xml</b> whose '
message += '<b><toolbox></b> tag is <b><toolbox tool_path="../shed_tools"></b>).<p/>See the '
- message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed#Automatic_installation_of_Galaxy_tool…" '
- message += 'target="_blank">Automatic installation of Galaxy tool shed repository tools into a local Galaxy instance</a> section of the '
- message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed" target="_blank">Galaxy tool shed wiki</a> for all of the details.'
+ message += '<a href="http://wiki.g2.bx.psu.edu/InstallingRepositoriesToGalaxy" target="_blank">Installation of Galaxy tool shed repository tools '
+ message += 'into a local Galaxy instance</a> section of the Galaxy tool shed wiki for all of the details.'
return trans.show_error_message( message )
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
diff -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 -r 69f446023855cd7ed585ca6dde5ee581043e61f0 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -620,7 +620,7 @@
can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, tool_config_filepath, changeset_revision )
if can_use_disk_file:
trans.app.config.tool_data_path = work_dir
- tool, valid, message = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, tool_config_filepath, work_dir )
+ tool, valid, message, sample_files = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, tool_config_filepath, work_dir )
if tool is not None:
invalid_files_and_errors_tups = check_tool_input_params( trans.app,
repo_files_dir,
@@ -637,7 +637,7 @@
message = concat_messages( message, message2 )
status = 'error'
else:
- tool, message = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir )
+ tool, message, sample_files = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir )
try:
shutil.rmtree( work_dir )
except:
diff -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 -r 69f446023855cd7ed585ca6dde5ee581043e61f0 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -2301,11 +2301,18 @@
can_use_disk_file = can_use_tool_config_disk_file( trans, repository, repo, full_path_to_tool_config, changeset_revision )
if can_use_disk_file:
trans.app.config.tool_data_path = work_dir
- tool, valid, message = handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, full_path_to_tool_config, work_dir )
+ tool, valid, message, sample_files = handle_sample_files_and_load_tool_from_disk( trans,
+ repo_files_dir,
+ full_path_to_tool_config,
+ work_dir )
if message:
status = 'error'
else:
- tool, message = handle_sample_files_and_load_tool_from_tmp_config( trans, repo, changeset_revision, tool_config_filename, work_dir )
+ tool, message, sample_files = handle_sample_files_and_load_tool_from_tmp_config( trans,
+ repo,
+ changeset_revision,
+ tool_config_filename,
+ work_dir )
if message:
status = 'error'
break
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Remove prefilled password/confirm/current fields from edit user info.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/5f739cf9187b/
changeset: 5f739cf9187b
user: dannon
date: 2012-09-25 17:30:16
summary: Remove prefilled password/confirm/current fields from edit user info.
affected #: 2 files
diff -r e327eba84158eb62d0c5c76e77a62ae999fc3779 -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -694,6 +694,7 @@
else:
widgets = user_type_form_definition.get_widgets( None, contents={}, **kwd )
return widgets
+
@web.expose
def manage_user_info( self, trans, cntrller, **kwd ):
'''Manage a user's login, password, public username, type, addresses, etc.'''
@@ -707,11 +708,6 @@
raise AssertionError, "The user id (%s) is not valid" % str( user_id )
webapp = get_webapp( trans, **kwd )
email = util.restore_text( params.get( 'email', user.email ) )
- # Do not sanitize passwords, so take from kwd
- # instead of params ( which were sanitized )
- current = kwd.get( 'current', '' )
- password = kwd.get( 'password', '' )
- confirm = kwd.get( 'confirm', '' )
username = util.restore_text( params.get( 'username', '' ) )
if not username:
username = user.username
@@ -721,7 +717,7 @@
user_type_form_definition = self.__get_user_type_form_definition( trans, user=user, **kwd )
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id == 'none' and user_type_form_definition is not None:
- user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
+ user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id )
widgets = self.__get_widgets( trans, user_type_form_definition, user=user, **kwd )
# user's addresses
@@ -739,14 +735,11 @@
cntrller=cntrller,
user=user,
email=email,
- current=current,
- password=password,
- confirm=confirm,
username=username,
user_type_fd_id_select_field=user_type_fd_id_select_field,
user_info_forms=user_info_forms,
user_type_form_definition=user_type_form_definition,
- widgets=widgets,
+ widgets=widgets,
addresses=addresses,
show_filter=show_filter,
webapp=webapp,
@@ -757,13 +750,11 @@
cntrller=cntrller,
user=user,
email=email,
- current=current,
- password=password,
- confirm=confirm,
username=username,
webapp=webapp,
message=message,
status=status )
+
# For REMOTE_USER, we need the ability to just edit the username
@web.expose
@web.require_login( "to manage the public name" )
diff -r e327eba84158eb62d0c5c76e77a62ae999fc3779 -r 5f739cf9187bde20a0b9d368bf83ffcac19eedc0 templates/user/info.mako
--- a/templates/user/info.mako
+++ b/templates/user/info.mako
@@ -59,16 +59,16 @@
%if not is_admin:
<div class="form-row"><label>Current password:</label>
- <input type="password" name="current" value="${current}" size="40"/>
+ <input type="password" name="current" value="" size="40"/></div>
%endif
<div class="form-row"><label>New password:</label>
- <input type="password" name="password" value="${password}" size="40"/>
+ <input type="password" name="password" value="" size="40"/></div><div class="form-row"><label>Confirm:</label>
- <input type="password" name="confirm" value="${confirm}" size="40"/>
+ <input type="password" name="confirm" value="" size="40"/></div><div class="form-row"><input type="submit" name="change_password_button" value="Save"/>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Cleanup user controller imports, remove import *'s.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/e327eba84158/
changeset: e327eba84158
user: dannon
date: 2012-09-25 17:07:25
summary: Cleanup user controller imports, remove import *'s.
affected #: 1 file
diff -r b4e09ad8245967bc757c57f09a467bafd91ea370 -r e327eba84158eb62d0c5c76e77a62ae999fc3779 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -1,16 +1,22 @@
"""
Contains the user interface in the Universe class
"""
+
+import glob
+import logging
+import os
+import socket
+import string
+import random
+from galaxy import web
+from galaxy import util, model
+from galaxy.model.orm import and_
+from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname
+from galaxy.util.json import from_json_string, to_json_string
+from galaxy.web import url_for
+from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin, get_webapp
+from galaxy.web.form_builder import CheckboxField, build_select_field
from galaxy.web.framework.helpers import time_ago, grids
-from galaxy.web.base.controller import *
-from galaxy.model.orm import *
-from galaxy import util, model
-import logging, os, string, re, socket, glob
-from random import choice
-from galaxy.web.form_builder import *
-from galaxy.util.json import from_json_string, to_json_string
-from galaxy.web.framework.helpers import iff
-from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname
log = logging.getLogger( __name__ )
@@ -916,7 +922,7 @@
chars = string.letters + string.digits
new_pass = ""
for i in range(15):
- new_pass = new_pass + choice(chars)
+ new_pass = new_pass + random.choice(chars)
host = trans.request.host.split(':')[0]
if host == 'localhost':
host = socket.getfqdn()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Fixes for ReferenceTracks to make compatible with recent refactoring.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/b4e09ad82459/
changeset: b4e09ad82459
user: jgoecks
date: 2012-09-25 16:52:28
summary: Fixes for ReferenceTracks to make compatible with recent refactoring.
affected #: 3 files
diff -r cdd39c933d24e11b4f99b5d24e5d1b108fea41ea -r b4e09ad8245967bc757c57f09a467bafd91ea370 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -729,7 +729,7 @@
/**
* Draw a single read.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, orig_seq) {
+ draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, ref_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
@@ -743,12 +743,12 @@
// Gap is needed so that read is offset and hence first base can be drawn on read.
// TODO-FIX: using this gap offsets reads so that their start is not visually in sync with other tracks.
- if ((mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) {
+ if ((mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
gap = Math.round(w_scale/2);
}
if (!cigar) {
// If no cigar string, then assume all matches
- cigar = [ [0, orig_seq.length] ];
+ cigar = [ [0, ref_seq.length] ];
}
for (var cig_id = 0, len = cigar.length; cig_id < len; cig_id++) {
var cig = cigar[cig_id],
@@ -782,7 +782,8 @@
case "=": // Equals.
if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
// Draw.
- var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
+ // -1 b/c sequence data is 1-based but painter is 0-based.
+ var seq = ref_seq.slice(seq_offset - 1, seq_offset + cig_len);
if (gap > 0) {
ctx.fillStyle = block_color;
ctx.fillRect(s_start - gap, y_center + 1, s_end - s_start, 9);
@@ -838,7 +839,8 @@
var insert_x_coord = s_start - gap;
if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
+ // -1 b/c sequence data is 1-based but painter is 0-based.
+ var seq = ref_seq.slice(seq_offset - 1, seq_offset + cig_len);
// Insertion point is between the sequence start and the previous base: (-gap) moves
// back from sequence start to insertion point.
if (this.prefs.show_insertions) {
@@ -849,7 +851,7 @@
// Draw sequence.
// X center is offset + start - <half_sequence_length>
var x_center = s_start - (s_end - s_start)/2;
- if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) {
+ if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
@@ -885,7 +887,7 @@
}
}
else {
- if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > char_width_px) {
+ if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
}
diff -r cdd39c933d24e11b4f99b5d24e5d1b108fea41ea -r b4e09ad8245967bc757c57f09a467bafd91ea370 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -3427,7 +3427,7 @@
this.content_div.css("border", "none");
this.data_url = reference_url + "/" + this.view.dbkey;
this.data_url_extra_params = {reference: true};
- this.data_manager = new ReferenceTrackDataManager({
+ this.data_manager = new visualization.ReferenceTrackDataManager({
data_url: this.data_url
});
this.hide_contents();
diff -r cdd39c933d24e11b4f99b5d24e5d1b108fea41ea -r b4e09ad8245967bc757c57f09a467bafd91ea370 static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -356,6 +356,13 @@
});
var ReferenceTrackDataManager = GenomeDataManager.extend({
+ initialize: function(options) {
+ // Use generic object in place of dataset and set urlRoot to fetch data.
+ var dataset_placeholder = new Backbone.Model();
+ dataset_placeholder.urlRoot = options.data_url;
+ this.set('dataset', dataset_placeholder);
+ },
+
load_data: function(low, high, mode, resolution, extra_params) {
if (resolution > 1) {
// Now that data is pre-fetched before draw, we don't load reference tracks
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: HTML-escape registration fields. Remove prefilled password/confirm on create kickback.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/cdd39c933d24/
changeset: cdd39c933d24
user: dannon
date: 2012-09-25 16:35:45
summary: HTML-escape registration fields. Remove prefilled password/confirm on create kickback.
affected #: 2 files
diff -r d6d0c963712a9f85a6a2baede6ec402285088823 -r cdd39c933d24e11b4f99b5d24e5d1b108fea41ea lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -493,6 +493,7 @@
message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' )
success = True
return ( message, status, user, success )
+
@web.expose
def logout( self, trans, webapp='galaxy', logout_all=False ):
if webapp == 'galaxy':
@@ -513,6 +514,7 @@
message=message,
status='done',
active_view="user" )
+
@web.expose
def create( self, trans, cntrller='user', redirect_url='', refresh_frames=[], **kwd ):
params = util.Params( kwd )
@@ -583,8 +585,6 @@
return trans.fill_template( '/user/register.mako',
cntrller=cntrller,
email=email,
- password=password,
- confirm=confirm,
username=transform_publicname( trans, username ),
subscribe_checked=subscribe_checked,
user_type_fd_id_select_field=user_type_fd_id_select_field,
@@ -597,6 +597,7 @@
refresh_frames=refresh_frames,
message=message,
status=status )
+
def __register( self, trans, cntrller, subscribe_checked, **kwd ):
email = util.restore_text( kwd.get( 'email', '' ) )
password = kwd.get( 'password', '' )
diff -r d6d0c963712a9f85a6a2baede6ec402285088823 -r cdd39c933d24e11b4f99b5d24e5d1b108fea41ea templates/user/register.mako
--- a/templates/user/register.mako
+++ b/templates/user/register.mako
@@ -3,7 +3,7 @@
%if redirect_url:
<script type="text/javascript">
- top.location.href = '${redirect_url}';
+ top.location.href = '${redirect_url | h}';
</script>
%endif
@@ -42,21 +42,21 @@
<div class="toolFormTitle">Create account</div><div class="form-row"><label>Email address:</label>
- <input type="text" name="email" value="${email}" size="40"/>
- <input type="hidden" name="webapp" value="${webapp}" size="40"/>
- <input type="hidden" name="redirect" value="${redirect}" size="40"/>
+ <input type="text" name="email" value="${email | h}" size="40"/>
+ <input type="hidden" name="webapp" value="${webapp | h}" size="40"/>
+ <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label>
- <input type="password" name="password" value="${password}" size="40"/>
+ <input type="password" name="password" value="" size="40"/></div><div class="form-row"><label>Confirm password:</label>
- <input type="password" name="confirm" value="${confirm}" size="40"/>
+ <input type="password" name="confirm" value="" size="40"/></div><div class="form-row"><label>Public name:</label>
- <input type="text" name="username" size="40" value="${username}"/>
+ <input type="text" name="username" size="40" value="${username |h}"/>
%if webapp == 'galaxy':
<div class="toolParamHelp" style="clear: both;">
Your public name is an identifier that will be used to generate addresses for information
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Viz framework: (a) improvements in setting dataset type when returning infomation; (b) transition Circster to use GenomeDataManager rather than custom data structures.
by Bitbucket 25 Sep '12
by Bitbucket 25 Sep '12
25 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/d6d0c963712a/
changeset: d6d0c963712a
user: jgoecks
date: 2012-09-25 15:18:00
summary: Viz framework: (a) improvements in setting dataset type when returning infomation; (b) transition Circster to use GenomeDataManager rather than custom data structures.
affected #: 7 files
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -113,7 +113,7 @@
class GenomeDataProvider( BaseDataProvider ):
""" Base class for genome data providers. """
- data_type = None
+ dataset_type = None
"""
Mapping from column name to payload data; this mapping is used to create
@@ -179,12 +179,21 @@
"""
Returns data for complete genome.
"""
- dataset_summary = []
+ genome_data = []
for chrom_info in chroms_info[ 'chrom_info' ]:
- summary = self.get_data( chrom_info[ 'chrom' ], 0, chrom_info[ 'len' ], **kwargs )
- dataset_summary.append( summary )
+ chrom = chrom_info[ 'chrom' ]
+ chrom_len = chrom_info[ 'len' ]
+ chrom_data = self.get_data( chrom, 0, chrom_len, **kwargs )
+ if chrom_data:
+ chrom_data[ 'region' ] = "%s:%i-%i" % ( chrom, 0, chrom_len )
+ chrom_data[ 'dataset_type' ] = self.dataset_type
+ genome_data.append( chrom_data )
- return dataset_summary
+ return {
+ 'data': genome_data,
+ 'dataset_type': self.dataset_type
+ }
+
def get_filters( self ):
"""
@@ -316,7 +325,7 @@
class TabixDataProvider( FilterableMixin, GenomeDataProvider ):
- data_type = 'tabix'
+ dataset_type = 'tabix'
"""
Tabix index data provider for the Galaxy track browser.
@@ -358,7 +367,7 @@
#
class IntervalDataProvider( GenomeDataProvider ):
- data_type = 'interval_index'
+ dataset_type = 'interval_index'
"""
Processes interval data from native format to payload format.
@@ -444,7 +453,7 @@
Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
"""
- data_type = 'interval_index'
+ dataset_type = 'interval_index'
def get_iterator( self, chrom, start, end ):
raise Exception( "Unimplemented Method" )
@@ -541,7 +550,7 @@
for large datasets.
"""
- data_type = 'interval_index'
+ dataset_type = 'interval_index'
def get_iterator( self, chrom=None, start=None, end=None ):
# Read first line in order to match chrom naming format.
@@ -581,7 +590,7 @@
col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } }
- data_type = 'bai'
+ dataset_type = 'bai'
def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
"""
@@ -687,7 +696,7 @@
for large datasets.
"""
- data_type = 'tabix'
+ dataset_type = 'tabix'
def get_iterator( self, chrom, start, end ):
# Read first line in order to match chrom naming format.
@@ -721,7 +730,7 @@
Summary tree data provider for the Galaxy track browser.
"""
- data_type = 'summary_tree'
+ dataset_type = 'summary_tree'
CACHE = LRUCache( 20 ) # Store 20 recently accessed indices for performance
@@ -765,7 +774,13 @@
if results == "detail" or results == "draw":
return results
else:
- return results, stats[ level ][ "max" ], stats[ level ]["avg" ], stats[ level ][ "delta" ]
+ return {
+ 'dataset_type': self.dataset_type,
+ 'data': results,
+ 'max': stats[ level ][ "max" ],
+ 'avg': stats[ level ][ "avg" ],
+ 'delta': stats[ level ][ "delta" ]
+ }
def has_data( self, chrom ):
"""
@@ -788,7 +803,7 @@
is reported in 1-based, closed format, i.e. SAM/BAM format.
"""
- data_type = 'bai'
+ dataset_type = 'bai'
def get_filters( self ):
"""
@@ -970,7 +985,7 @@
class SamDataProvider( BamDataProvider ):
- data_type = 'bai'
+ dataset_type = 'bai'
def __init__( self, converted_dataset=None, original_dataset=None, dependencies=None ):
""" Create SamDataProvider. """
@@ -987,7 +1002,7 @@
BBI data provider for the Galaxy track browser.
"""
- data_type = 'bigwig'
+ dataset_type = 'bigwig'
def valid_chroms( self ):
# No way to return this info as of now
@@ -1122,7 +1137,7 @@
"""
col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
- data_type = 'interval_index'
+ dataset_type = 'interval_index'
def write_data_to_file( self, regions, filename ):
source = open( self.original_dataset.file_name )
@@ -1201,7 +1216,7 @@
for large datasets.
"""
- data_type = 'interval_index'
+ dataset_type = 'interval_index'
def get_iterator( self, chrom, start, end ):
"""
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 lib/galaxy/web/api/datasets.py
--- a/lib/galaxy/web/api/datasets.py
+++ b/lib/galaxy/web/api/datasets.py
@@ -139,12 +139,15 @@
if mode == "Coverage":
# Get summary using minimal cutoffs.
indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
- summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], detail_cutoff=0, draw_cutoff=0 )
+ summary = indexer.get_data( chrom, low, high,
+ resolution=kwargs[ 'resolution' ],
+ level=kwargs.get( 'level', None ),
+ detail_cutoff=0, draw_cutoff=0 )
if summary == "detail":
# Use maximum level of detail--2--to get summary data no matter the resolution.
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], level=2, detail_cutoff=0, draw_cutoff=0 )
frequencies, max_v, avg_v, delta = summary
- return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
+ return { 'dataset_type': indexer.dataset_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and mode == "Auto":
# Only check for summary_tree if it's Auto mode (which is the default)
@@ -153,14 +156,13 @@
indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ] )
if summary is None:
- return { 'dataset_type': indexer.data_type, 'data': None }
+ return { 'dataset_type': indexer.dataset_type, 'data': None }
if summary == "draw":
kwargs["no_detail"] = True # meh
extra_info = "no_detail"
elif summary != "detail":
- frequencies, max_v, avg_v, delta = summary
- return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
+ return summary
# Get data provider.
data_provider = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='data' )
@@ -171,7 +173,7 @@
# Get and return data from data_provider.
result = data_provider.get_data( chrom, int( low ), int( high ), int( start_val ), int( max_vals ), **kwargs )
- result.update( { 'dataset_type': data_provider.data_type, 'extra_info': extra_info } )
+ result.update( { 'dataset_type': data_provider.dataset_type, 'extra_info': extra_info } )
return result
def _raw_data( self, trans, dataset, **kwargs ):
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -760,7 +760,7 @@
original_dataset=dataset,
source='index' )
# HACK: pass in additional params, which are only used for summary tree data, not BBI data.
- track[ 'genome_wide_data' ] = { 'data': data_provider.get_genome_data( chroms_info, level=4, detail_cutoff=0, draw_cutoff=0 ) }
+ track[ 'preloaded_data' ] = data_provider.get_genome_data( chroms_info, level=4, detail_cutoff=0, draw_cutoff=0 )
return trans.fill_template( 'visualization/circster.mako', viz_config=viz_config, genome=genome )
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 static/scripts/viz/circster.js
--- a/static/scripts/viz/circster.js
+++ b/static/scripts/viz/circster.js
@@ -1,4 +1,4 @@
-define( ["libs/d3", "viz/visualization"], function( d3, visualization ) {
+define( ["libs/underscore", "libs/d3", "viz/visualization"], function(_, d3, visualization) {
// General backbone style inheritence
var Base = function() { this.initialize && this.initialize.apply(this, arguments); }; Base.extend = Backbone.Model.extend;
@@ -48,7 +48,8 @@
// Compute radius start based on model, will be centered
// and fit entirely inside element by default.
init_radius_start = ( Math.min(width, height)/2 -
- this.model.get('tracks').length * (this.dataset_arc_height + this.track_gap) );
+ this.model.get('tracks').length * (this.dataset_arc_height + this.track_gap) ),
+ tracks = this.model.get('tracks');
// Set up SVG element.
var svg = d3.select(self.$el[0])
@@ -59,26 +60,37 @@
// Set up zooming, dragging.
.append('svg:g')
.call(d3.behavior.zoom().on('zoom', function() {
+ // Do zoom.
svg.attr("transform",
"translate(" + d3.event.translate + ")" +
" scale(" + d3.event.scale + ")");
- var utils = new SVGUtils();
- var visible_elts = d3.selectAll('path').filter(function(d, i) {
+
+ // Update visible elements with more data.
+ var utils = new SVGUtils(),
+ tracks_and_chroms_to_update = {};
+
+ tracks.each(function(t) {
+ tracks_and_chroms_to_update[t.id] = [];
+ });
+
+ d3.selectAll('path.chrom-data').filter(function(d, i) {
return utils.is_visible(this, svg);
+ }).each(function(d, i) {
+ var elt_data = $.data(this, "chrom_data");
+ tracks_and_chroms_to_update[elt_data.track.id].push(elt_data.chrom);
});
- visible_elts.each(function(d, i) {
- // TODO: redraw visible elements.
- });
+
+ // TODO: update tracks and chroms.
+ //console.log(tracks_and_chroms_to_update);
}))
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.append('svg:g');
// -- Render each dataset in the visualization. --
- this.model.get('tracks').each(function(track, index) {
- var dataset = track.get('genome_wide_data'),
- radius_start = init_radius_start + index * (dataset_arc_height + self.track_gap),
- track_renderer_class = (dataset instanceof visualization.GenomeWideBigWigData ?
+ tracks.each(function(track, index) {
+ var radius_start = init_radius_start + index * (dataset_arc_height + self.track_gap),
+ track_renderer_class = (track.get('track_type') === 'LineTrack' ?
CircsterBigWigTrackRenderer :
CircsterSummaryTreeTrackRenderer );
@@ -160,12 +172,17 @@
render_data: function(svg) {
var self = this,
chrom_arcs = this.chroms_layout(),
- dataset = this.options.track.get('genome_wide_data'),
+ track = this.options.track,
r_start = this.options.radius_start,
r_end = this.options.radius_end,
+
+ genome_wide_data = track.get_genome_wide_data(this.options.genome),
// Merge chroms layout with data.
- layout_and_data = _.zip(chrom_arcs, dataset.get('data')),
+ layout_and_data = _.zip(chrom_arcs, genome_wide_data),
+
+ // Get min, max in data.
+ bounds = this.get_bounds(genome_wide_data),
// Do dataset layout for each chromosome's data using pie layout.
chroms_data_layout = _.map(layout_and_data, function(chrom_info) {
@@ -173,7 +190,7 @@
data = chrom_info[1];
return self.render_chrom_data(svg, chrom_arc, data,
r_start, r_end,
- dataset.get('min'), dataset.get('max'));
+ bounds.min, bounds.max);
});
return chroms_data_layout;
@@ -187,7 +204,7 @@
/**
* Renders quantitative data with the form [x, value] and assumes data is equally spaced across
- * chromosome.
+ * chromosome. Attachs a dict with track and chrom name information to DOM element.
*/
render_quantitative_data: function(svg, chrom_arc, data, inner_radius, outer_radius, min, max) {
// Radius scaler.
@@ -212,14 +229,25 @@
.angle(line.angle());
// Render data.
- var parent = svg.datum(data);
-
- parent.append("path")
- .attr("class", "chrom-data")
- .attr("d", area);
- }
+ var parent = svg.datum(data),
+ path = parent.append("path")
+ .attr("class", "chrom-data")
+ .attr("d", area);
-})
+ // Attach dict with track and chrom info for path.
+ $.data(path[0][0], "chrom_data", {
+ track: this.options.track,
+ chrom: chrom_arc.data.chrom
+ });
+ },
+
+ /**
+ * Returns an object with min, max attributes denoting the minimum and maximum
+ * values for the track.
+ */
+ get_bounds: function() {}
+
+});
/**
* Layout for summary tree data in a circster visualization.
@@ -235,7 +263,19 @@
return null;
}
- return this.render_quantitative_data(svg, chrom_arc, chrom_data[0], inner_radius, outer_radius, min, max);
+ return this.render_quantitative_data(svg, chrom_arc, chrom_data.data, inner_radius, outer_radius, min, max);
+ },
+
+ get_bounds: function(data) {
+ // Get max across data.
+ var max_data = _.map(data, function(d) {
+ if (!d || typeof d === 'string') { return 0; }
+ return d.max;
+ });
+ return {
+ min: 0,
+ max: (max_data && typeof max_data !== 'string' ? _.max(max_data) : 0)
+ };
}
});
@@ -252,6 +292,27 @@
if (data.length === 0) { return; }
return this.render_quantitative_data(svg, chrom_arc, data, inner_radius, outer_radius, min, max);
+ },
+
+ get_bounds: function(data) {
+ // Set max across dataset by extracting all values, flattening them into a
+ // single array, and getting the min and max.
+ var values = _.flatten( _.map(data, function(d) {
+ if (d) {
+ // Each data point has the form [position, value], so return all values.
+ return _.map(d.data, function(p) {
+ return p[1];
+ });
+ }
+ else {
+ return 0;
+ }
+ }) );
+
+ return {
+ min: _.min(values),
+ max: _.max(values)
+ };
}
});
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -3550,8 +3550,7 @@
track.vertical_range = undefined;
return $.getJSON( track.dataset.url(),
{ data_type: 'data', stats: true, chrom: track.view.chrom, low: 0,
- high: track.view.max_high, hda_ldda: track.hda_ldda, dataset_id:
- track.dataset_id }, function(result) {
+ high: track.view.max_high, hda_ldda: track.hda_ldda }, function(result) {
track.container_div.addClass( "line-track" );
var data = result.data;
if ( isNaN(parseFloat(track.prefs.min_value)) || isNaN(parseFloat(track.prefs.max_value)) ) {
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -1,4 +1,4 @@
-define( ["mvc/data", "viz/trackster/util" ], function(data, util) {
+define( ["mvc/data", "viz/trackster/util" ], function(data_mod, util_mod) {
/**
* Model, view, and controller objects for Galaxy visualization framework.
@@ -138,7 +138,6 @@
dataset: null,
filters_manager: null,
data_type: "data",
- genome_wide_summary_data: null,
data_mode_compatible: function(entry, mode) { return true; },
can_subset: function(entry) { return false; }
}),
@@ -150,7 +149,7 @@
data_is_ready: function() {
var dataset = this.get('dataset'),
ready_deferred = $.Deferred(),
- ss_deferred = new util.ServerStateDeferred({
+ ss_deferred = new util_mod.ServerStateDeferred({
ajax_settings: {
url: this.get('dataset').url(),
data: {
@@ -176,7 +175,6 @@
var dataset = this.get('dataset'),
params = {
query: query,
- dataset_id: dataset.id,
hda_ldda: dataset.get('hda_ldda'),
data_type: 'features'
};
@@ -188,22 +186,17 @@
*/
load_data: function(region, mode, resolution, extra_params) {
// Setup data request params.
- var params = {
+ var dataset = this.get('dataset'),
+ params = {
"data_type": this.get('data_type'),
"chrom": region.get('chrom'),
"low": region.get('start'),
"high": region.get('end'),
"mode": mode,
- "resolution": resolution
- },
- dataset = this.get('dataset');
-
- // ReferenceDataManager does not have dataset.
- if (dataset) {
- params.dataset_id = dataset.id;
- params.hda_ldda = dataset.get('hda_ldda');
- }
-
+ "resolution": resolution,
+ "hda_ldda": dataset.get('hda_ldda')
+ };
+
$.extend(params, extra_params);
// Add track filters to params.
@@ -533,69 +526,53 @@
model: BrowserBookmark
});
-var GenomeWideBigWigData = Backbone.Model.extend({
- defaults: {
- data: null,
- min: 0,
- max: 0
- },
-
- initialize: function(options) {
- // Set max across dataset by extracting all values, flattening them into a
- // single array, and getting the min and max.
- var values = _.flatten( _.map(this.get('data'), function(d) {
- if (d.data.length !== 0) {
- // Each data point has the form [position, value], so return all values.
- return _.map(d.data, function(p) {
- return p[1];
- });
- }
- else {
- return 0;
- }
- }) );
- this.set('max', _.max(values));
- this.set('min', _.min(values));
- }
-});
-
-/**
- * Genome-wide summary tree dataset.
- */
-var GenomeWideSummaryTreeData = Backbone.RelationalModel.extend({
- defaults: {
- data: null,
- min: 0,
- max: 0
- },
-
- initialize: function(options) {
- // Set max across dataset.
- var max_data = _.max(this.get('data'), function(d) {
- if (!d || typeof d === 'string') { return 0; }
- return d[1];
- });
- this.attributes.max = (max_data && typeof max_data !== 'string' ? max_data[1] : 0);
- }
-});
-
/**
* A track of data in a genome visualization.
*/
// TODO: rename to Track and merge with Trackster's Track object.
-var BackboneTrack = data.Dataset.extend({
+var BackboneTrack = data_mod.Dataset.extend({
initialize: function(options) {
// Dataset id is unique ID for now.
this.set('id', options.dataset_id);
- // Create genome-wide dataset if available.
- var genome_wide_data = this.get('genome_wide_data');
- if (genome_wide_data) {
- var gwd_class = (this.get('track_type') === 'LineTrack' ?
- GenomeWideBigWigData : GenomeWideSummaryTreeData);
- this.set('genome_wide_data', new gwd_class(genome_wide_data));
+ // Set up data manager.
+ var data_manager = new GenomeDataManager({
+ dataset: this
+ });
+ this.set('data_manager', data_manager);
+
+ // If there's preloaded data, add it to data manager.
+ var preloaded_data = this.get('preloaded_data');
+ if (preloaded_data) {
+ // Increase size to accomodate all preloaded data.
+ data_manager.set('num_elements', preloaded_data.data.length);
+
+ // Put data into manager.
+ _.each(preloaded_data.data, function(entry) {
+ data_manager.set_data(entry.region, entry);
+ });
}
+ },
+
+ /**
+ * Returns an array of data with each entry representing one chromosome/contig
+ * of data.
+ */
+ get_genome_wide_data: function(genome) {
+ var self = this,
+ data_manager = this.get('data_manager');
+
+ // Map chromosome data into track data.
+ return _.map(genome.get('chroms_info').chrom_info, function(chrom_info) {
+ return data_manager.get_elt(
+ new GenomeRegion({
+ chrom: chrom_info.chrom,
+ start: 0,
+ end: chrom_info.len
+ })
+ );
+ });
}
});
@@ -716,7 +693,7 @@
},
id = $(this).val();
if ($(this).attr("name") !== "id") {
- data['hda_ldda'] = 'ldda';
+ data.hda_ldda = 'ldda';
}
requests[requests.length] = $.ajax({
url: add_track_async_url + "/" + id,
@@ -754,8 +731,6 @@
GenomeRegion: GenomeRegion,
GenomeRegionCollection: GenomeRegionCollection,
GenomeVisualization: GenomeVisualization,
- GenomeWideBigWigData: GenomeWideBigWigData,
- GenomeWideSummaryTreeData: GenomeWideSummaryTreeData,
ReferenceTrackDataManager: ReferenceTrackDataManager,
TrackBrowserRouter: TrackBrowserRouter,
TrackConfig: TrackConfig,
diff -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a -r d6d0c963712a9f85a6a2baede6ec402285088823 templates/visualization/circster.mako
--- a/templates/visualization/circster.mako
+++ b/templates/visualization/circster.mako
@@ -23,6 +23,7 @@
require.config({
baseUrl: "${h.url_for('/static/scripts')}",
shim: {
+ "libs/underscore": { exports: "_" },
"libs/d3": { exports: "d3" }
}
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/36ca2ecd42fd/
changeset: 36ca2ecd42fd
user: dannon
date: 2012-09-24 19:55:35
summary: Prevent potential login XSS.
affected #: 2 files
diff -r 327632b4f9992b2c3f4b9c6f705bed1f4e05914d -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -395,6 +395,7 @@
use_panels=use_panels,
message=message,
status=status ) )
+
@web.expose
@web.require_login( 'manage OpenIDs' )
def openid_manage( self, trans, webapp='galaxy', **kwd ):
@@ -409,10 +410,10 @@
action='openid_disassociate',
use_panels=use_panels,
id=kwd['id'] ) )
-
kwd['redirect'] = kwd.get( 'redirect', url_for( controller='user', action='openid_manage', use_panels=True ) ).strip()
kwd['openid_providers'] = trans.app.openid_providers
return self.user_openid_grid( trans, **kwd )
+
@web.expose
def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ):
'''Handle Galaxy Log in'''
@@ -423,6 +424,9 @@
header = ''
user = None
email = kwd.get( 'email', '' )
+ #Sanitize webapp login here, once, since it can be reflected to the user in messages/etc.
+ #Only text is valid.
+ webapp = util.sanitize_text(webapp)
if kwd.get( 'login_button', False ):
if webapp == 'galaxy' and not refresh_frames:
if trans.app.config.require_login:
diff -r 327632b4f9992b2c3f4b9c6f705bed1f4e05914d -r 36ca2ecd42fdbc581b0caa253b66a136aa0f848a templates/user/login.mako
--- a/templates/user/login.mako
+++ b/templates/user/login.mako
@@ -30,7 +30,7 @@
%if redirect_url:
<script type="text/javascript">
- top.location.href = '${redirect_url}';
+ top.location.href = '${redirect_url | h}';
</script>
%endif
@@ -81,9 +81,9 @@
<form name="login" id="login" action="${form_action}" method="post" ><div class="form-row"><label>Email address:</label>
- <input type="text" name="email" value="${email}" size="40"/>
- <input type="hidden" name="webapp" value="${webapp}" size="40"/>
- <input type="hidden" name="redirect" value="${redirect}" size="40"/>
+ <input type="text" name="email" value="${email | h}" size="40"/>
+ <input type="hidden" name="webapp" value="${webapp | h}" size="40"/>
+ <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label>
@@ -107,8 +107,8 @@
<div class="form-row"><label>OpenID URL:</label><input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/>
- <input type="hidden" name="webapp" value="${webapp}" size="40"/>
- <input type="hidden" name="redirect" value="${redirect}" size="40"/>
+ <input type="hidden" name="webapp" value="${webapp | h}" size="40"/>
+ <input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row">
Or, authenticate with your <select name="openid_provider">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
24 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/327632b4f999/
changeset: 327632b4f999
user: carlfeberhard
date: 2012-09-24 19:47:23
summary: scatterplot: add require.js
affected #: 3 files
diff -r 8b7dfceabe3ea6cc15001f05a623157e95f1bcb7 -r 327632b4f9992b2c3f4b9c6f705bed1f4e05914d static/scripts/viz/scatterplot.js
--- a/static/scripts/viz/scatterplot.js
+++ b/static/scripts/viz/scatterplot.js
@@ -1,3 +1,9 @@
+define([
+ "../libs/underscore",
+ "../libs/d3",
+ "../mvc/base-mvc"
+
+], function(){
/* =============================================================================
todo:
outside this:
@@ -355,11 +361,11 @@
};
}
-//// ugh...this seems like the wrong way to use models
-//var ScatterplotModel = BaseModel.extend( LoggableMixin ).extend({
-// logger : console
-//});
-
+//==============================================================================
+/**
+ * Scatterplot control UI as a backbone view
+ *
+ */
var ScatterplotView = BaseView.extend( LoggableMixin ).extend({
//logger : console,
tagName : 'form',
@@ -370,15 +376,19 @@
},
initialize : function( attributes ){
- if( !attributes.dataset ){
+ if( !attributes || !attributes.dataset ){
throw( "ScatterplotView requires a dataset" );
} else {
this.dataset = attributes.dataset;
}
+
+ // passed from mako helper
+ //TODO: integrate to galaxyPaths
this.apiDatasetsURL = attributes.apiDatasetsURL;
+
+ // set up the basic chart infrastructure with config (if any)
this.chartConfig = attributes.chartConfig || {};
this.log( 'this.chartConfig:', this.chartConfig );
-
this.plot = new TwoVarScatterplot( this.chartConfig );
},
@@ -422,18 +432,23 @@
},
renderScatterplot : function(){
+ // parse the column values for both
+ // indeces (for the data fetch) and names (for the graph)
var view = this,
- url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&';
+ url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&',
+
xSelector = this.$el.find( '[name="x-column"]' ),
xVal = xSelector.val(),
xName = xSelector.children( '[value="' + xVal + '"]' ).text(),
+
ySelector = this.$el.find( '[name="y-column"]' ),
yVal = ySelector.val(),
yName = ySelector.children( '[value="' + yVal + '"]' ).text();
- //TODO
this.log( xName, yName );
+
this.chartConfig.xLabel = xName;
this.chartConfig.yLabel = yName;
+
//TODO: alter directly
view.plot.updateConfig( this.chartConfig );
@@ -441,6 +456,7 @@
//TODO: other vals: max, start, page
//TODO: chart config
+ // fetch the data, sending chosen columns to the server
url += jQuery.param({
columns : '[' + [ xVal, yVal ] + ']'
});
@@ -450,6 +466,7 @@
url : url,
dataType : 'json',
success : function( response ){
+ //TODO: server sends back an endpoint, cache for next pagination request
view.endpoint = response.endpoint;
view.plot.render(
// pull apart first two regardless of number of columns
@@ -464,3 +481,8 @@
}
});
+//==============================================================================
+return {
+ //TwoVarScatterplot : TwoVarScatterplot,
+ ScatterplotView : ScatterplotView
+};});
\ No newline at end of file
diff -r 8b7dfceabe3ea6cc15001f05a623157e95f1bcb7 -r 327632b4f9992b2c3f4b9c6f705bed1f4e05914d templates/base_panels.mako
--- a/templates/base_panels.mako
+++ b/templates/base_panels.mako
@@ -48,7 +48,17 @@
<!--[if lt IE 7]>
${h.js( 'libs/IE/IE7', 'libs/IE/ie7-recalc' )}
<![endif]-->
- ${h.js( 'libs/jquery/jquery', 'libs/json2', 'libs/bootstrap', 'libs/underscore', 'libs/backbone/backbone', 'libs/backbone/backbone-relational', 'libs/handlebars.runtime', 'mvc/ui', 'galaxy.base' )}
+ ${h.js(
+ 'libs/jquery/jquery',
+ 'libs/json2',
+ 'libs/bootstrap',
+ 'libs/underscore',
+ 'libs/backbone/backbone',
+ 'libs/backbone/backbone-relational',
+ 'libs/handlebars.runtime',
+ 'mvc/ui',
+ 'galaxy.base'
+ )}
<script type="text/javascript">
// Set up needed paths.
var galaxy_paths = new GalaxyPaths({
diff -r 8b7dfceabe3ea6cc15001f05a623157e95f1bcb7 -r 327632b4f9992b2c3f4b9c6f705bed1f4e05914d templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -6,25 +6,25 @@
<style type="text/css">
.title {
- margin: 0px;
+ margin: 0px;
padding: 8px;
background-color: #ebd9b2;
border: 2px solid #ebd9b2;
}
.subtitle {
- margin: 0px;
+ margin: 0px;
padding: 0px 8px 8px 16px;
background-color: #ebd9b2;
- color: white;
- font-size: small;
+ color: white;
+ font-size: small;
}
#chart-settings-form {
/*from width + margin of chart?*/
- float: right;
+ float: right;
width: 100%;
- margin: 0px;
+ margin: 0px;
padding-top: 1em;
}
@@ -45,80 +45,67 @@
overflow: auto;
}
-.clear {
- clear: both;
- margin: 0px;
-}
-
-
-svg .chart {
- /*shape-rendering: crispEdges;*/
-}
-
svg .grid-line {
- fill: none;
- stroke: lightgrey;
- stroke-opacity: 0.5;
- shape-rendering: crispEdges;
- stroke-dasharray: 3, 3;
+ fill: none;
+ stroke: lightgrey;
+ stroke-opacity: 0.5;
+ shape-rendering: crispEdges;
+ stroke-dasharray: 3, 3;
}
svg .axis path, svg .axis line {
- fill: none;
- stroke: black;
- shape-rendering: crispEdges;
+ fill: none;
+ stroke: black;
+ shape-rendering: crispEdges;
}
svg .axis text {
- font-family: sans-serif;
- font-size: 12px;
+ font-family: sans-serif;
+ font-size: 12px;
}
-
svg .glyph {
- stroke: none;
- fill: black;
- fill-opacity: 0.2;
+ stroke: none;
+ fill: black;
+ fill-opacity: 0.2;
}
-
+
</style>
-
+
</%def><%def name="javascripts()">
${parent.javascripts()}
-${h.js(
- "libs/underscore",
- "libs/backbone/backbone",
- "libs/backbone/backbone-relational",
- "libs/d3",
- "mvc/base-mvc",
- "viz/scatterplot"
-)}
+${h.js( "libs/require" )}
<script type="text/javascript">
-$(function() {
- var hda = ${h.to_json_string( hda )},
- historyID = '${historyID}'
- apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}";
- //?? hmmmm
- //kwargs = ${h.to_json_string( kwargs )};
-
- var settingsForm = new ScatterplotView({
- dataset : hda,
- el : $( '#chart-settings-form' ),
+require.config({ baseUrl : "${h.url_for( '/static/scripts' )}", });
+
+require([ "viz/scatterplot" ], function( scatterplot ){
+
+ var hda = ${h.to_json_string( hda )},
+ historyID = '${historyID}'
+ apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}";
+ //?? hmmmm
+ //kwargs = ${h.to_json_string( kwargs )};
+
+ var settingsForm = new scatterplot.ScatterplotView({
+ dataset : hda,
+ el : $( '#chart-settings-form' ),
apiDatasetsURL : apiDatasetsURL,
+
chartConfig : {
containerSelector : '#chart-holder',
marginTop : 20,
}
- }).render();
+ }).render();
});
+
</script></%def><%def name="body()"><h2 class="title">Scatterplot of '${hda['name']}'</h2><p class="subtitle">${hda['misc_info']}</p>
- <div id="chart-holder"></div>
- <div id="chart-settings-form"></div>
+ <div id="chart-holder"></div>
+ <div id="chart-settings-form"></div></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
23 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/8b7dfceabe3e/
changeset: 8b7dfceabe3e
user: jgoecks
date: 2012-09-24 01:34:11
summary: Fix Cuffdiff parameter group naming.
affected #: 1 file
diff -r 3574c1fa4cb3494f82fd1915c63da6154b230756 -r 8b7dfceabe3ea6cc15001f05a623157e95f1bcb7 tools/ngs_rna/cuffdiff_wrapper.xml
--- a/tools/ngs_rna/cuffdiff_wrapper.xml
+++ b/tools/ngs_rna/cuffdiff_wrapper.xml
@@ -22,11 +22,11 @@
--cds_diff_output=$cds_diff
--promoters_diff_output=$promoters_diff
- ## Set paired-end data parameters?
- #if $singlePaired.sPaired == "Yes":
- -m $singlePaired.frag_mean_len
- -s $singlePaired.frag_len_std_dev
- #end if
+ ## Set advanced data parameters?
+ #if $additional.sAdditional == "Yes":
+ -m $additional.frag_mean_len
+ -s $additional.frag_len_std_dev
+ #end if
## Normalization?
#if str($do_normalization) == "Yes":
@@ -113,15 +113,15 @@
</when><when value="No"></when></conditional>
- <conditional name="singlePaired">
- <param name="sPaired" type="select" label="Set Parameters for Paired-end Reads? (not recommended)">
+ <conditional name="additional">
+ <param name="sAdditional" type="select" label="Set Additional Parameters? (not recommended)"><option value="No">No</option><option value="Yes">Yes</option></param><when value="No"></when><when value="Yes">
- <param name="frag_mean_len" type="integer" value="20" label="Average Fragment Length"/>
- <param name="frag_len_std_dev" type="integer" value="20" label="Fragment Length Standard Deviation"/>
+ <param name="frag_mean_len" type="integer" value="200" label="Average Fragment Length"/>
+ <param name="frag_len_std_dev" type="integer" value="80" label="Fragment Length Standard Deviation"/></when></conditional></inputs>
@@ -154,7 +154,7 @@
<param name="min_alignment_count" value="0" /><param name="do_bias_correction" value="No" /><param name="do_normalization" value="No" />
- <param name="sPaired" value="single"/>
+ <param name="sAdditional" value="No"/><!--
Line diffs are needed because cuffdiff does not produce deterministic output.
TODO: can we find datasets that lead to deterministic behavior?
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/3574c1fa4cb3/
changeset: 3574c1fa4cb3
user: carlfeberhard
date: 2012-09-22 00:39:04
summary: fixes to ae57c837ab03
affected #: 3 files
diff -r 45f11c9b4affd9006f1f7159368567cd412d20b8 -r 3574c1fa4cb3494f82fd1915c63da6154b230756 lib/galaxy/visualization/data_providers/basic.py
--- a/lib/galaxy/visualization/data_providers/basic.py
+++ b/lib/galaxy/visualization/data_providers/basic.py
@@ -90,7 +90,7 @@
if( skip_comments
and start_val == 0
and self.original_dataset.metadata.comment_lines ):
- start_val = self.original_dataset.metadata.comment_lines
+ start_val = int( self.original_dataset.metadata.comment_lines ) + 1
response = {}
response[ 'data' ] = data = []
@@ -102,6 +102,8 @@
"column index (%d) must be less" % ( column )
+ " than the number of columns: %d" % ( self.original_dataset.metadata.columns ) )
+ #print columns, start_val, max_vals, skip_comments, kwargs
+
# alter meta by column_selectors (if any)
def cast_val( val, type ):
""" Cast value based on type. """
@@ -125,8 +127,9 @@
fields = line.split()
fields_len = len( fields )
#TODO: this will return the wrong number of columns for abberrant lines
- data.append([ cast_val( fields[c], self.original_dataset.metadata.column_types[c] )
- for c in columns if ( c < fields_len ) ])
+ line_data = [ cast_val( fields[c], self.original_dataset.metadata.column_types[c] )
+ for c in columns if ( c < fields_len ) ]
+ data.append( line_data )
response[ 'endpoint' ] = dict( last_line=( count - 1 ), file_ptr=f.tell() )
f.close()
diff -r 45f11c9b4affd9006f1f7159368567cd412d20b8 -r 3574c1fa4cb3494f82fd1915c63da6154b230756 lib/galaxy/web/api/datasets.py
--- a/lib/galaxy/web/api/datasets.py
+++ b/lib/galaxy/web/api/datasets.py
@@ -189,13 +189,9 @@
# Return data.
data = None
data_provider = trans.app.data_provider_registry.get_data_provider( trans, raw=True, original_dataset=dataset )
+ print 'data_provider:', data_provider
- if data_provider == ColumnDataProvider:
- #pre: should have column kwargs
- #print 'kwargs:', kwargs
- #TODO??: could default to first two here
- assert 'cols' in kwargs, (
- "ColumnDataProvider needs a 'cols' parameter in the query string" )
+ if isinstance( data_provider, ColumnDataProvider ):
data = data_provider.get_data( **kwargs )
else:
diff -r 45f11c9b4affd9006f1f7159368567cd412d20b8 -r 3574c1fa4cb3494f82fd1915c63da6154b230756 templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -2,22 +2,21 @@
<%def name="stylesheets()">
${parent.stylesheets()}
-##${h.css( "history", "autocomplete_tagging", "trackster", "overcast/jquery-ui-1.8.5.custom", "library" )}
<style type="text/css">
-* { margin: 0px, padding: 0px; }
.title {
- margin: 0px;
+ margin: 0px;
padding: 8px;
background-color: #ebd9b2;
+ border: 2px solid #ebd9b2;
}
.subtitle {
- margin: 0px;
- padding: 0px, 8px, 8px, 16px;
+ margin: 0px;
+ padding: 0px 8px 8px 16px;
background-color: #ebd9b2;
- color: grey;
+ color: white;
font-size: small;
}
@@ -25,7 +24,7 @@
/*from width + margin of chart?*/
float: right;
width: 100%;
- background-color: #ebd9b2;
+ margin: 0px;
padding-top: 1em;
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Circster: add support for drawing a generic quantitative track and draw summary tree data using a single path.
by Bitbucket 21 Sep '12
by Bitbucket 21 Sep '12
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/45f11c9b4aff/
changeset: 45f11c9b4aff
user: jgoecks
date: 2012-09-21 23:44:41
summary: Circster: add support for drawing a generic quantitative track and draw summary tree data using a single path.
affected #: 1 file
diff -r ae57c837ab039ded7f5056252c2e630988080faf -r 45f11c9b4affd9006f1f7159368567cd412d20b8 static/scripts/viz/circster.js
--- a/static/scripts/viz/circster.js
+++ b/static/scripts/viz/circster.js
@@ -46,7 +46,7 @@
width = self.$el.width(),
height = self.$el.height(),
// Compute radius start based on model, will be centered
- // and fit entirely inside element by default
+ // and fit entirely inside element by default.
init_radius_start = ( Math.min(width, height)/2 -
this.model.get('tracks').length * (this.dataset_arc_height + this.track_gap) );
@@ -67,7 +67,7 @@
return utils.is_visible(this, svg);
});
visible_elts.each(function(d, i) {
- console.log(this.attr('title'));
+ // TODO: redraw visible elements.
});
}))
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
@@ -78,7 +78,9 @@
this.model.get('tracks').each(function(track, index) {
var dataset = track.get('genome_wide_data'),
radius_start = init_radius_start + index * (dataset_arc_height + self.track_gap),
- track_renderer_class = (dataset instanceof visualization.GenomeWideBigWigData ? CircsterBigWigTrackRenderer : CircsterSummaryTreeTrackRenderer );
+ track_renderer_class = (dataset instanceof visualization.GenomeWideBigWigData ?
+ CircsterBigWigTrackRenderer :
+ CircsterSummaryTreeTrackRenderer );
var track_renderer = new track_renderer_class({
track: track,
@@ -105,12 +107,12 @@
var genome_arcs = this.chroms_layout(),
radius_start = this.options.radius_start,
radius_end = this.options.radius_end,
- base_arc = svg.append("g").attr("id", "inner-arc"),
+ track_parent_elt = svg.append("g").attr("id", "inner-arc"),
arc_gen = d3.svg.arc()
.innerRadius(radius_start)
.outerRadius(radius_end),
// Draw arcs.
- chroms_elts = base_arc.selectAll("#inner-arc>path")
+ chroms_elts = track_parent_elt.selectAll("#inner-arc>path")
.data(genome_arcs).enter().append("path")
.attr("d", arc_gen)
.style("stroke", "#ccc")
@@ -118,12 +120,13 @@
.append("title").text(function(d) { return d.data.chrom; });
// Render data.
- this.render_data(svg);
+ this.render_data(track_parent_elt);
+ // Apply prefs.
var prefs = this.options.track.get('prefs'),
block_color = prefs.block_color;
if (!block_color) { block_color = prefs.color; }
- svg.selectAll('path.chrom-data').style('stroke', block_color).style('fill', block_color);
+ track_parent_elt.selectAll('path.chrom-data').style('stroke', block_color).style('fill', block_color);
},
/**
@@ -148,7 +151,7 @@
/**
* Render chromosome data and attach elements to svg.
*/
- render_chrom_data: function(chrom_arc, chrom_data, inner_radius, outer_radius, max) {
+ render_chrom_data: function(svg, chrom_arc, data, inner_radius, outer_radius, max) {
},
/**
@@ -167,8 +170,8 @@
// Do dataset layout for each chromosome's data using pie layout.
chroms_data_layout = _.map(layout_and_data, function(chrom_info) {
var chrom_arc = chrom_info[0],
- chrom_data = chrom_info[1];
- return self.render_chrom_data(svg, chrom_arc, chrom_data,
+ data = chrom_info[1];
+ return self.render_chrom_data(svg, chrom_arc, data,
r_start, r_end,
dataset.get('min'), dataset.get('max'));
});
@@ -178,55 +181,15 @@
});
/**
- * Layout for summary tree data in a circster visualization.
+ * Rendered for quantitative data.
*/
-var CircsterSummaryTreeTrackRenderer = CircsterTrackRenderer.extend({
-
- /**
- * Returns layouts for drawing a chromosome's data.
- */
- render_chrom_data: function(svg, chrom_arc, chrom_data, inner_radius, outer_radius, min, max) {
- // FIXME: draw as area:
- /*
- // If no chrom data, return null.
- if (!chrom_data || typeof chrom_data === "string") {
- return null;
- }
-
- var data = chrom_data[0],
- delta = chrom_data[3],
- scale = d3.scale.linear()
- .domain( [min, max] )
- .range( [inner_radius, outer_radius] ),
- arc_layout = d3.layout.pie().value(function(d) {
- return delta;
- })
- .startAngle(chrom_arc.startAngle)
- .endAngle(chrom_arc.endAngle),
- arcs = arc_layout(data);
-
- // Use scale to assign outer radius.
- _.each(data, function(datum, index) {
- arcs[index].outerRadius = scale(datum[1]);
- });
-
- return arcs;
- */
- }
-});
-
-/**
- * Layout for BigWig data in a circster visualization.
- */
-var CircsterBigWigTrackRenderer = CircsterTrackRenderer.extend({
+var CircsterQuantitativeTrackRenderer = CircsterTrackRenderer.extend({
/**
- * Render chromosome data and attach elements to svg.
+ * Renders quantitative data with the form [x, value] and assumes data is equally spaced across
+ * chromosome.
*/
- render_chrom_data: function(svg, chrom_arc, chrom_data, inner_radius, outer_radius, min, max) {
- var data = chrom_data.data;
- if (data.length === 0) { return; }
-
+ render_quantitative_data: function(svg, chrom_arc, data, inner_radius, outer_radius, min, max) {
// Radius scaler.
var radius = d3.scale.linear()
.domain([min, max])
@@ -237,14 +200,8 @@
.domain([0, data.length])
.range([chrom_arc.startAngle, chrom_arc.endAngle]);
- // FIXME:
- // *area is not necessary as long as 0 is used as the inner radius.
- // *could provide fill as an option.
-
- // Use both a line and area; area creates definition and line ensures that something is
- // always drawn.
var line = d3.svg.line.radial()
- .interpolate("linear-closed")
+ .interpolate("linear")
.radius(function(d) { return radius(d[1]); })
.angle(function(d, i) { return angle(i); });
@@ -260,12 +217,42 @@
parent.append("path")
.attr("class", "chrom-data")
.attr("d", area);
-
- parent.append("path")
- .attr("class", "chrom-data")
- .attr("d", line);
}
+})
+
+/**
+ * Layout for summary tree data in a circster visualization.
+ */
+var CircsterSummaryTreeTrackRenderer = CircsterQuantitativeTrackRenderer.extend({
+
+ /**
+ * Renders a chromosome's data.
+ */
+ render_chrom_data: function(svg, chrom_arc, chrom_data, inner_radius, outer_radius, min, max) {
+ // If no chrom data, return null.
+ if (!chrom_data || typeof chrom_data === "string") {
+ return null;
+ }
+
+ return this.render_quantitative_data(svg, chrom_arc, chrom_data[0], inner_radius, outer_radius, min, max);
+ }
+});
+
+/**
+ * Layout for BigWig data in a circster visualization.
+ */
+var CircsterBigWigTrackRenderer = CircsterQuantitativeTrackRenderer.extend({
+
+ /**
+ * Renders a chromosome's data.
+ */
+ render_chrom_data: function(svg, chrom_arc, chrom_data, inner_radius, outer_radius, min, max) {
+ var data = chrom_data.data;
+ if (data.length === 0) { return; }
+
+ return this.render_quantitative_data(svg, chrom_arc, data, inner_radius, outer_radius, min, max);
+ }
});
return {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: fixed(?) weird permissions on jquery-ui; scatterplot: major adjustments;
by Bitbucket 21 Sep '12
by Bitbucket 21 Sep '12
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/ae57c837ab03/
changeset: ae57c837ab03
user: carlfeberhard
date: 2012-09-21 22:42:29
summary: fixed(?) weird permissions on jquery-ui; scatterplot: major adjustments;
affected #: 8 files
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf lib/galaxy/visualization/data_providers/basic.py
--- a/lib/galaxy/visualization/data_providers/basic.py
+++ b/lib/galaxy/visualization/data_providers/basic.py
@@ -45,31 +45,64 @@
"""
iterator = self.get_iterator( chrom, start, end )
return self.process_data( iterator, start_val, max_vals, **kwargs )
+
def write_data_to_file( self, filename, **kwargs ):
"""
Write data in region defined by chrom, start, and end to a file.
"""
raise Exception( "Unimplemented Function" )
+
class ColumnDataProvider( BaseDataProvider ):
""" Data provider for columnar data """
+ MAX_LINES_RETURNED = 30000
- def __init__( self, original_dataset ):
+ def __init__( self, original_dataset, max_lines_returned=MAX_LINES_RETURNED ):
# Compatibility check.
if not isinstance( original_dataset.datatype, Tabular ):
raise Exception( "Data provider can only be used with tabular data" )
# Attribute init.
self.original_dataset = original_dataset
+ # allow throttling
+ self.max_lines_returned = max_lines_returned
- def get_data( self, cols, start_val=0, max_vals=sys.maxint, **kwargs ):
+ def get_data( self, columns, start_val=0, max_vals=None, skip_comments=True, **kwargs ):
"""
Returns data from specified columns in dataset. Format is list of lists
where each list is a line of data.
"""
-
- cols = from_json_string( cols )
+ #TODO: validate kwargs
+ try:
+ max_vals = int( max_vals )
+ max_vals = min([ max_vals, self.max_lines_returned ])
+ except ( ValueError, TypeError ):
+ max_vals = self.max_lines_returned
+ try:
+ start_val = int( start_val )
+ start_val = max([ start_val, 0 ])
+ except ( ValueError, TypeError ):
+ start_val = 0
+
+ # skip comment lines (if any/avail)
+ # pre: should have original_dataset and
+ if( skip_comments
+ and start_val == 0
+ and self.original_dataset.metadata.comment_lines ):
+ start_val = self.original_dataset.metadata.comment_lines
+
+ response = {}
+ response[ 'data' ] = data = []
+
+ #TODO bail if columns None, not parsable, not within meta.columns
+ # columns is an array of ints for now (should handle column names later)
+ columns = from_json_string( columns )
+ assert( all([ column < self.original_dataset.metadata.columns for column in columns ]) ),(
+ "column index (%d) must be less" % ( column )
+ + " than the number of columns: %d" % ( self.original_dataset.metadata.columns ) )
+
+ # alter meta by column_selectors (if any)
def cast_val( val, type ):
""" Cast value based on type. """
if type == 'int':
@@ -80,23 +113,23 @@
except: pass
return val
- data = []
f = open( self.original_dataset.file_name )
+ #TODO: add f.seek if given fptr in kwargs
for count, line in enumerate( f ):
if count < start_val:
continue
- if max_vals and count-start_val >= max_vals:
- message = self.error_max_vals % ( max_vals, "features" )
+
+ if ( count - start_val ) >= max_vals:
break
fields = line.split()
- #pre: column indeces should be avail in fields
- for col_index in cols:
- assert col_index < len( fields ), (
- "column index (%d) must be less than fields length: %d" % ( col_index, len( fields ) ) )
-
- data.append( [ cast_val( fields[c], self.original_dataset.metadata.column_types[c] ) for c in cols ] )
+ fields_len = len( fields )
+ #TODO: this will return the wrong number of columns for abberrant lines
+ data.append([ cast_val( fields[c], self.original_dataset.metadata.column_types[c] )
+ for c in columns if ( c < fields_len ) ])
+ response[ 'endpoint' ] = dict( last_line=( count - 1 ), file_ptr=f.tell() )
f.close()
-
- return data
+
+ return response
+
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf lib/galaxy/web/api/datasets.py
--- a/lib/galaxy/web/api/datasets.py
+++ b/lib/galaxy/web/api/datasets.py
@@ -38,26 +38,27 @@
return str( e )
# Use data type to return particular type of data.
- if data_type == 'state':
- rval = self._dataset_state( trans, dataset )
- elif data_type == 'converted_datasets_state':
- rval = self._converted_datasets_state( trans, dataset, kwd.get( 'chrom', None ) )
- elif data_type == 'data':
- rval = self._data( trans, dataset, **kwd )
- elif data_type == 'features':
- rval = self._search_features( trans, dataset, kwd.get( 'query ' ) )
- elif data_type == 'raw_data':
- rval = self._raw_data( trans, dataset, **kwd )
- elif data_type == 'track_config':
- rval = self.get_new_track_config( trans, dataset )
- else:
- # Default: return dataset as API value.
- try:
+ try:
+ if data_type == 'state':
+ rval = self._dataset_state( trans, dataset )
+ elif data_type == 'converted_datasets_state':
+ rval = self._converted_datasets_state( trans, dataset, kwd.get( 'chrom', None ) )
+ elif data_type == 'data':
+ rval = self._data( trans, dataset, **kwd )
+ elif data_type == 'features':
+ rval = self._search_features( trans, dataset, kwd.get( 'query ' ) )
+ elif data_type == 'raw_data':
+ rval = self._raw_data( trans, dataset, **kwd )
+ elif data_type == 'track_config':
+ rval = self.get_new_track_config( trans, dataset )
+ else:
+ # Default: return dataset as API value.
rval = dataset.get_api_value()
- except Exception, e:
- rval = "Error in dataset API at listing contents"
- log.error( rval + ": %s" % str(e) )
- trans.response.status = 500
+
+ except Exception, e:
+ rval = "Error in dataset API at listing contents"
+ log.error( rval + ": %s" % str(e), exc_info=True )
+ trans.response.status = 500
return rval
def _dataset_state( self, trans, dataset, **kwargs ):
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -800,26 +800,26 @@
return self.get_visualization( trans, id )
@web.expose
- def scatterplot( self, trans, dataset_id, cols ):
+ def scatterplot( self, trans, dataset_id, **kwargs ):
# Get HDA.
hda = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True )
-
- # get some metadata for the page
hda_dict = hda.get_api_value()
- #title = "Scatter plot of {name}:".format( **hda_dict )
- #subtitle = "{misc_info}".format( **hda_dict )
+ hda_dict[ 'id' ] = dataset_id
+ if( hda_dict[ 'metadata_column_names' ] == None
+ and hasattr( hda.datatype, 'column_names' ) ):
+ hda_dict[ 'metadata_column_names' ] = hda.datatype.column_names
+ history_id = trans.security.encode_id( hda.history.id )
#TODO: add column data
# Read data.
- data_provider = ColumnDataProvider( original_dataset=hda )
- data = data_provider.get_data( cols )
+ #data_provider = ColumnDataProvider( original_dataset=hda, **kwargs )
+ #data = data_provider.get_data()
# Return plot.
return trans.fill_template_mako( "visualization/scatterplot.mako",
- title=hda.name, subtitle=hda.info,
- hda=hda,
- data=data )
-
+ hda=hda_dict,
+ historyID=history_id,
+ kwargs=kwargs )
@web.json
def bookmarks_from_dataset( self, trans, hda_id=None, ldda_id=None ):
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf static/scripts/viz/scatterplot.js
--- /dev/null
+++ b/static/scripts/viz/scatterplot.js
@@ -0,0 +1,466 @@
+/* =============================================================================
+todo:
+ outside this:
+ BUG: visualization menu doesn't disappear
+ BUG?: get column_names (from datatype if necessary)
+ BUG: single vis in popupmenu should have tooltip with that name NOT 'Visualizations'
+
+ ??: maybe better to do this with a canvas...
+
+ move renderScatter plot to obj, possibly view?
+
+ fix x axis - adjust ticks when tick labels are long - move odds down and extend tick line
+
+ provide callback in view to load data incrementally - for large sets
+
+ paginate
+ handle rerender
+ use endpoint (here and on the server (fileptr))
+ fetch (new?) data
+ handle rerender
+
+ selectable list of preset column comparisons (rnaseq etc.)
+ multiple plots on one page (small multiples)
+
+ where are bad dataprovider params handled? api/datasets?
+
+ config changes to the graph
+ render stats on the data (max, min, count)
+ render warning on long data (> maxDataPoints)
+ adjust endpoint
+
+ loading indicator
+
+ download svg -> base64 encode
+ dress up ui
+
+ incorporate glyphs, glyph state renderers
+
+ validate columns selection (here or server)
+
+ ?? ensure svg styles thru d3 or css?
+ d3: configable (easily)
+ css: standard - better maintenance
+ ? override at config
+
+============================================================================= */
+/**
+ * Two Variable scatterplot visualization using d3
+ * Uses semi transparent circles to show density of data in x, y grid
+ * usage :
+ * var plot = new TwoVarScatterplot({ containerSelector : 'div#my-plot', ... })
+ * plot.render( xColumnData, yColumnData );
+ *
+ * depends on: d3, underscore
+ */
+function TwoVarScatterplot( config ){
+ var plot = this,
+ GUESS_AT_SVG_CHAR_WIDTH = 10,
+ GUESS_AT_SVG_CHAR_HEIGHT = 12,
+ PADDING = 8,
+ X_LABEL_TOO_LONG_AT = 5;
+
+ //this.debugging = true;
+ this.log = function(){
+ if( this.debugging && console && console.debug ){
+ var args = Array.prototype.slice.call( arguments );
+ args.unshift( this.toString() );
+ console.debug.apply( null, args );
+ }
+ };
+ this.log( 'new TwoVarScatterplot:', config );
+
+ // ........................................................ set up chart config
+ // config will default to these values when not passed in
+ //NOTE: called on new
+ this.defaults = {
+ id : 'TwoVarScatterplot',
+ containerSelector : 'body',
+ maxDataPoints : 30000,
+ bubbleRadius : 4,
+ entryAnimDuration : 500,
+ //TODO: no effect?
+ xNumTicks : 10,
+ yNumTicks : 10,
+ xAxisLabelBumpY : 40,
+ yAxisLabelBumpX : -35,
+ width : 500,
+ height : 500,
+ //TODO: anyway to make this a sub-obj?
+ marginTop : 50,
+ marginRight : 50,
+ marginBottom : 50,
+ marginLeft : 50,
+ xMin : null,
+ xMax : null,
+ yMin : null,
+ yMax : null,
+ xLabel : "X",
+ yLabel : "Y"
+ };
+ this.config = _.extend( {}, this.defaults, config );
+
+ this.updateConfig = function( newConfig ){
+ _.extend( this.config, newConfig );
+ };
+
+ // ........................................................ helpers
+ this.toString = function(){
+ return this.config.id;
+ };
+ this.translateStr = function( x, y ){
+ return 'translate(' + x + ',' + y + ')';
+ };
+ this.rotateStr = function( d, x, y ){
+ return 'rotate(' + d + ',' + x + ',' + y + ')';
+ };
+
+ // ........................................................ initial element creation
+ //NOTE: called on new
+ this.svg = d3.select( this.config.containerSelector )
+ .append( "svg:svg" ).attr( "class", "chart" ).style( 'display', 'none' );
+ this.content = this.svg.append( "svg:g" ).attr( "class", "content" );
+
+ this.xAxis = this.content.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'x-axis' );
+ this.xAxisLabel = this.xAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'x-axis-label' );
+
+ this.yAxis = this.content.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'y-axis' );
+ this.yAxisLabel = this.yAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'y-axis-label' );
+
+ this.log( 'built svg:', d3.selectAll( 'svg' ) );
+
+ this.adjustChartDimensions = function(){
+ this.svg
+ .attr( "width", this.config.width + ( this.config.marginRight + this.config.marginLeft ) )
+ .attr( "height", this.config.height + ( this.config.marginTop + this.config.marginBottom ) )
+ // initial is hidden - show it
+ .style( 'display', 'block' );
+
+ // move content group away from margins
+ this.content = this.svg.select( "g.content" )
+ .attr( "transform", this.translateStr( this.config.marginLeft, this.config.marginTop ) );
+ };
+
+ // ........................................................ data and scales
+ this.preprocessData = function( data ){
+ // set a cap on the data, limit to first n points
+ return data.slice( 0, this.config.maxDataPoints );
+ };
+
+ this.setUpDomains = function( xCol, yCol ){
+ this.xMin = this.config.xMin || d3.min( xCol );
+ this.xMax = this.config.xMax || d3.max( xCol );
+ this.yMin = this.config.yMin || d3.min( yCol );
+ this.yMax = this.config.yMax || d3.max( yCol );
+ };
+
+ this.setUpScales = function(){
+ // Interpolation for x, y based on data domains
+ this.xScale = d3.scale.linear()
+ .domain([ this.xMin, this.xMax ])
+ .range([ 0, this.config.width ]),
+ this.yScale = d3.scale.linear()
+ .domain([ this.yMin, this.yMax ])
+ .range([ this.config.height, 0 ]);
+ };
+
+ // ........................................................ axis and ticks
+ this.setUpXAxis = function(){
+ // origin: bottom, left
+ //TODO: incoporate top, right
+ this.xAxisFn = d3.svg.axis()
+ .scale( this.xScale )
+ .ticks( this.config.xNumTicks )
+ .orient( 'bottom' );
+ this.xAxis// = content.select( 'g#x-axis' )
+ .attr( 'transform', this.translateStr( 0, this.config.height ) )
+ .call( this.xAxisFn );
+ this.log( 'xAxis:', this.xAxis );
+
+ //TODO: this isn't reliable with -/+ ranges - better to go thru each tick
+ this.xLongestLabel = d3.max( _.map( [ this.xMin, this.xMax ],
+ function( number ){ return ( String( number ) ).length; } ) );
+ this.log( 'xLongestLabel:', this.xLongestLabel );
+
+ if( this.xLongestLabel >= X_LABEL_TOO_LONG_AT ){
+ //TODO: adjust ticks when tick labels are long - move odds down and extend tick line
+ // (for now) hide them
+ this.xAxis.selectAll( 'g' ).filter( ':nth-child(odd)' ).style( 'display', 'none' );
+ }
+
+ this.xAxisLabel// = xAxis.select( 'text#x-axis-label' )
+ .attr( 'x', this.config.width / 2 )
+ .attr( 'y', this.config.xAxisLabelBumpY )
+ .attr( 'text-anchor', 'middle' )
+ .text( this.config.xLabel );
+ this.log( 'xAxisLabel:', this.xAxisLabel );
+ };
+
+ this.setUpYAxis = function(){
+ this.yAxisFn = d3.svg.axis()
+ .scale( this.yScale )
+ .ticks( this.config.yNumTicks )
+ .orient( 'left' );
+ this.yAxis// = content.select( 'g#y-axis' )
+ .call( this.yAxisFn );
+ this.log( 'yAxis:', this.yAxis );
+
+ this.yLongestLabel = d3.max( _.map( [ this.yMin, this.yMax ],
+ function( number ){ return ( String( number ) ).length; } ) );
+ this.log( 'yLongestLabel:', this.yLongestLabel );
+
+ //TODO: ugh ... so clumsy
+ //TODO: this isn't reliable with -/+ ranges - better to go thru each tick
+ var neededY = this.yLongestLabel * GUESS_AT_SVG_CHAR_WIDTH + ( PADDING );
+
+ // increase width for xLongerStr, increase margin for y
+ //TODO??: (or transform each number: 2k)
+ if( this.config.yAxisLabelBumpX > -( neededY ) ){
+ this.config.yAxisLabelBumpX = -( neededY );
+ }
+ if( this.config.marginLeft < neededY ){
+ this.config.marginLeft = neededY + GUESS_AT_SVG_CHAR_HEIGHT;
+ // update dimensions, translations
+ this.adjustChartDimensions();
+ }
+ this.log( 'this.config.yAxisLableBumpx, this.config.marginLeft:',
+ this.config.yAxisLabelBumpX, this.config.marginLeft );
+
+ this.yAxisLabel// = yAxis.select( 'text#y-axis-label' )
+ .attr( 'x', this.config.yAxisLabelBumpX )
+ .attr( 'y', this.config.height / 2 )
+ .attr( 'text-anchor', 'middle' )
+ .attr( 'transform', this.rotateStr( -90, this.config.yAxisLabelBumpX, this.config.height / 2 ) )
+ .text( this.config.yLabel );
+ this.log( 'yAxisLabel:', this.yAxisLabel );
+ };
+
+ // ........................................................ grid lines
+ this.renderGrid = function(){
+ // VERTICAL
+ // select existing
+ this.vGridLines = this.content.selectAll( 'line.v-grid-line' )
+ .data( this.xScale.ticks( this.xAxisFn.ticks()[0] ) );
+
+ // append any extra lines needed (more ticks)
+ this.vGridLines.enter().append( 'svg:line' )
+ .classed( 'grid-line v-grid-line', true );
+
+ // update the attributes of existing and appended
+ this.vGridLines
+ .attr( 'x1', this.xScale )
+ .attr( 'y1', 0 )
+ .attr( 'x2', this.xScale )
+ .attr( 'y2', this.config.height );
+
+ // remove unneeded (less ticks)
+ this.vGridLines.exit().remove();
+ this.log( 'vGridLines:', this.vGridLines );
+
+ // HORIZONTAL
+ this.hGridLines = this.content.selectAll( 'line.h-grid-line' )
+ .data( this.yScale.ticks( this.yAxisFn.ticks()[0] ) );
+
+ this.hGridLines.enter().append( 'svg:line' )
+ .classed( 'grid-line h-grid-line', true );
+
+ this.hGridLines
+ .attr( 'x1', 0 )
+ .attr( 'y1', this.yScale )
+ .attr( 'x2', this.config.width )
+ .attr( 'y2', this.yScale );
+
+ this.hGridLines.exit().remove();
+ this.log( 'hGridLines:', this.hGridLines );
+ };
+
+ // ........................................................ data points
+ //TODO: these to config ...somehow
+ //TODO: use these in renderDatapoints ...somehow
+ this.glyphEnterState = function( d3Elem ){
+
+ };
+ this.glyphFinalState = function( d3Elem ){
+
+ };
+ this.glyphExitState = function( d3Elem ){
+
+ };
+
+ this.renderDatapoints = function( xCol, yCol ){
+
+ var xPosFn = function( d, i ){
+ return plot.xScale( xCol[ i ] );
+ };
+ var yPosFn = function( d, i ){
+ return plot.yScale( yCol[ i ] );
+ };
+
+ // select all existing glyphs and compare to incoming data
+ // enter() will yield those glyphs that need to be added
+ // exit() will yield existing glyphs that need to be removed
+ this.datapoints = this.content.selectAll( ".glyph" )
+ .data( xCol );
+
+ // enter - new data to be added as glyphs: give them a 'entry' position and style
+ this.datapoints.enter()
+ .append( "svg:circle" ).attr( "class", "glyph" )
+ // start all bubbles at corner...
+ .attr( "cx", xPosFn )
+ .attr( "cy", 0 )
+ .attr( "r", 0 );
+
+ // for all existing glyphs and those that need to be added: transition anim to final state
+ this.datapoints
+ // ...animate to final position
+ .transition().duration( this.config.entryAnimDuration )
+ .attr( "cx", xPosFn )
+ .attr( "cy", yPosFn )
+ .attr( "r", this.config.bubbleRadius );
+
+ // glyphs that need to be removed: transition to from normal state to 'exit' state, remove from DOM
+ this.datapoints.exit()
+ .transition().duration( this.config.entryAnimDuration )
+ .attr( "cy", this.config.height )
+ .attr( "r", 0 )
+ .style( "fill-opacity", 0 )
+ .remove();
+
+ this.log( this.datapoints, 'glyphs rendered' );
+ };
+
+ this.render = function( xCol, yCol ){
+ //pre: columns passed are numeric
+ this.log( 'renderScatterplot', xCol.length, yCol.length, this.config );
+
+ //pre: xCol.len == yCol.len
+ //TODO: ^^ isn't necessarily true with current ColumnDataProvider
+ xCol = this.preprocessData( xCol );
+ yCol = this.preprocessData( yCol );
+ this.log( 'xCol len', xCol.length, 'yCol len', yCol.length );
+
+ //TODO: compute min, max on server.
+ this.setUpDomains( xCol, yCol );
+ this.log( 'xMin, xMax, yMin, yMax:', this.xMin, this.xMax, this.yMin, this.yMax );
+
+ this.setUpScales();
+ this.adjustChartDimensions();
+
+ this.setUpXAxis();
+ this.setUpYAxis();
+
+ this.renderGrid();
+ this.renderDatapoints( xCol, yCol );
+ //TODO: on hover red line to axes, display values
+ };
+}
+
+//// ugh...this seems like the wrong way to use models
+//var ScatterplotModel = BaseModel.extend( LoggableMixin ).extend({
+// logger : console
+//});
+
+var ScatterplotView = BaseView.extend( LoggableMixin ).extend({
+ //logger : console,
+ tagName : 'form',
+ className : 'scatterplot-settings-form',
+
+ events : {
+ 'click #render-button' : 'renderScatterplot'
+ },
+
+ initialize : function( attributes ){
+ if( !attributes.dataset ){
+ throw( "ScatterplotView requires a dataset" );
+ } else {
+ this.dataset = attributes.dataset;
+ }
+ this.apiDatasetsURL = attributes.apiDatasetsURL;
+ this.chartConfig = attributes.chartConfig || {};
+ this.log( 'this.chartConfig:', this.chartConfig );
+
+ this.plot = new TwoVarScatterplot( this.chartConfig );
+ },
+
+ render : function(){
+ //TODO: to template
+ var view = this,
+ html = '',
+ columnHtml = '';
+ // build column select controls for each x, y (based on name if available)
+ // ugh...hafta preprocess
+ this.dataset.metadata_column_types = this.dataset.metadata_column_types.split( ', ' );
+ _.each( this.dataset.metadata_column_types, function( type, index ){
+ // use only numeric columns
+ if( type === 'int' || type === 'float' ){
+ var name = 'column ' + index;
+ // label with the name if available
+ if( view.dataset.metadata_column_names ){
+ name = view.dataset.metadata_column_names[ index ];
+ }
+ columnHtml += '<option value="' + index + '">' + name + '</column>';
+ }
+ });
+
+ // column selector containers
+ html += '<div id="x-column-input">';
+ html += '<label for="">Data column for X: </label><select name="x-column">' + columnHtml + '</select>';
+ html += '</div>';
+
+ html += '<div id="y-column-input">';
+ html += '<label for="">Data column for Y: </label><select name="y-column">' + columnHtml + '</select>';
+ html += '</div>';
+
+ html += '<input id="render-button" type="button" value="Draw" />';
+ html += '<div class="clear"></div>';
+
+ //TODO: other vals: max_vals, start_val, pagination
+
+ this.$el.append( html );
+ this.$el.find( '#render-button' );
+ return this;
+ },
+
+ renderScatterplot : function(){
+ var view = this,
+ url = this.apiDatasetsURL + '/' + this.dataset.id + '?data_type=raw_data&';
+ xSelector = this.$el.find( '[name="x-column"]' ),
+ xVal = xSelector.val(),
+ xName = xSelector.children( '[value="' + xVal + '"]' ).text(),
+ ySelector = this.$el.find( '[name="y-column"]' ),
+ yVal = ySelector.val(),
+ yName = ySelector.children( '[value="' + yVal + '"]' ).text();
+ //TODO
+ this.log( xName, yName );
+ this.chartConfig.xLabel = xName;
+ this.chartConfig.yLabel = yName;
+ //TODO: alter directly
+ view.plot.updateConfig( this.chartConfig );
+
+ //TODO: validate columns - minimally: we can assume either set by selectors or via a good query string
+ //TODO: other vals: max, start, page
+ //TODO: chart config
+
+ url += jQuery.param({
+ columns : '[' + [ xVal, yVal ] + ']'
+ });
+ this.log( 'url:', url );
+
+ jQuery.ajax({
+ url : url,
+ dataType : 'json',
+ success : function( response ){
+ view.endpoint = response.endpoint;
+ view.plot.render(
+ // pull apart first two regardless of number of columns
+ _.map( response.data, function( columns ){ return columns[0]; } ),
+ _.map( response.data, function( columns ){ return columns[1]; } )
+ );
+ },
+ error : function( xhr, status, error ){
+ alert( 'ERROR:' + status + '\n' + error );
+ }
+ });
+ }
+});
+
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf templates/root/history.mako
--- a/templates/root/history.mako
+++ b/templates/root/history.mako
@@ -194,6 +194,17 @@
};
};
+function create_scatterplot_action_fn( url, params ){
+ action = function() {
+ var galaxy_main = $( window.parent.document ).find( 'iframe#galaxy_main' ),
+ final_url = url + '/scatterplot?' + $.param(params);
+ galaxy_main.attr( 'src', final_url );
+ $( 'div.popmenu-wrapper' ).remove();
+ return false;
+ };
+ return action;
+}
+
/**
* Create popup menu for visualization icon.
*/
@@ -208,14 +219,20 @@
// Create visualization action.
create_viz_action = function(visualization) {
var action;
- if (visualization === 'trackster') {
- action = create_trackster_action_fn(vis_url, params, dbkey);
- }
- else {
- action = function() {
- window.parent.location = vis_url + '/' + visualization + '?' +
- $.param(params);
- };
+ switch( visualization ){
+
+ case 'trackster':
+ action = create_trackster_action_fn(vis_url, params, dbkey);
+ break;
+
+ case 'scatterplot':
+ action = create_scatterplot_action_fn( vis_url, params );
+ break;
+
+ default:
+ action = function(){
+ window.parent.location = vis_url + '/' + visualization + '?' + $.param(params);
+ }
}
return action;
},
@@ -234,6 +251,7 @@
// Set up action or menu.
if (visualizations.length === 1) {
// No need for popup menu because there's a single visualization.
+ icon.attr( 'title', visualizations[0] );
icon.click(create_viz_action(visualizations[0]));
}
else {
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf templates/root/history_common.mako
--- a/templates/root/history_common.mako
+++ b/templates/root/history_common.mako
@@ -230,10 +230,10 @@
## information--URL base, dataset id, dbkey, visualizations--in anchor.
<%
visualizations = data.get_visualizations()
- ## HACK: if there are visualizations, only provide trackster for now since others
- ## are not ready.
+ ## HACK: if there are visualizations, only provide trackster for now
+ ## since others are not ready. - comment out to see all WIP visualizations
if visualizations:
- visualizations = [ 'trackster' ]
+ visualizations = [ vis for vis in visualizations if vis in [ 'trackster' ] ]
%>
%if visualizations:
<a href="${h.url_for( controller='visualization' )}"
diff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 -r ae57c837ab039ded7f5056252c2e630988080faf templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -2,23 +2,61 @@
<%def name="stylesheets()">
${parent.stylesheets()}
-${h.css( "history", "autocomplete_tagging", "trackster", "overcast/jquery-ui-1.8.5.custom", "library" )}
+##${h.css( "history", "autocomplete_tagging", "trackster", "overcast/jquery-ui-1.8.5.custom", "library" )}
<style type="text/css">
* { margin: 0px, padding: 0px; }
+.title {
+ margin: 0px;
+ padding: 8px;
+ background-color: #ebd9b2;
+}
+
.subtitle {
- margin-left: 1em;
- margin-top: -1em;
+ margin: 0px;
+ padding: 0px, 8px, 8px, 16px;
+ background-color: #ebd9b2;
color: grey;
font-size: small;
}
-.chart {
+#chart-settings-form {
+ /*from width + margin of chart?*/
+ float: right;
+ width: 100%;
+ background-color: #ebd9b2;
+ padding-top: 1em;
+}
+
+#chart-settings-form > * {
+ margin: 8px;
+}
+
+#chart-settings-form input, #chart-settings-form select {
+ width: 30%;
+ max-width: 256px;
+}
+
+#chart-settings-form [value=Draw] {
+ float: right;
+}
+
+#chart-holder {
+ overflow: auto;
+}
+
+.clear {
+ clear: both;
+ margin: 0px;
+}
+
+
+svg .chart {
/*shape-rendering: crispEdges;*/
}
-.grid-line {
+svg .grid-line {
fill: none;
stroke: lightgrey;
stroke-opacity: 0.5;
@@ -26,18 +64,18 @@
stroke-dasharray: 3, 3;
}
-.axis path, .axis line {
+svg .axis path, svg .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
-.axis text {
+svg .axis text {
font-family: sans-serif;
font-size: 12px;
}
-circle.bubble {
+svg .glyph {
stroke: none;
fill: black;
fill-opacity: 0.2;
@@ -49,156 +87,39 @@
<%def name="javascripts()">
${parent.javascripts()}
-${h.js( "libs/d3" )}
+${h.js(
+ "libs/underscore",
+ "libs/backbone/backbone",
+ "libs/backbone/backbone-relational",
+ "libs/d3",
+ "mvc/base-mvc",
+ "viz/scatterplot"
+)}
<script type="text/javascript">
-/* =============================================================================
-todo:
- validate columns (here or server)
- send: type, column title/name in JSON
-
- move to obj, possibly view?
- fetch (new?) data
- config changes to the graph
- download svg (png?)
-
-============================================================================= */
-function translateStr( x, y ){
- return 'translate(' + x + ',' + y + ')';
-}
-function rotateStr( d, x, y ){
- return 'rotate(' + d + ',' + x + ',' + y + ')';
-}
-
$(function() {
- // Constants
- var data = ${data},
- MAX_DATA_POINTS = 30000,
- BUBBLE_RADIUS = 5,
- ENTRY_ANIM_DURATION = 500,
- X_TICKS = 10, Y_TICKS = 10,
- X_AXIS_LABEL_BUMP_Y = 40,
- Y_AXIS_LABEL_BUMP_X = -35,
- WIDTH = 300,
- HEIGHT = 300,
- MARGIN= 50,
- xLabel = "Magnitude",
- yLabel = "Depth";
-
- // set a cap on the data, limit to first n points
- data = data.slice( 0, MAX_DATA_POINTS );
+ var hda = ${h.to_json_string( hda )},
+ historyID = '${historyID}'
+ apiDatasetsURL = "${h.url_for( controller='/api/datasets' )}";
+ //?? hmmmm
+ //kwargs = ${h.to_json_string( kwargs )};
- // split the data into columns
- //TODO: compute min, max on server.
- var col1_data = data.map( function(e) { return e[0] }),
- col2_data = data.map( function(e) { return e[1] }),
- xMin = d3.min( col1_data ),
- xMax = d3.max( col1_data ),
- yMin = d3.min( col2_data ),
- yMax = d3.max( col2_data );
- //console.log( 'col1_data:', col1_data );
- //console.log( 'col2_data:', col2_data );
- //console.log( 'xMin, xMax, yMin, yMax:', xMin, xMax, yMin, yMax );
-
- // Set up.
- d3.select( "body" ).append( "svg:svg" )
- .attr( "width", WIDTH + ( MARGIN * 2 ) )
- .attr( "height", HEIGHT + ( MARGIN * 2 ) )
- .attr( "class", "chart" );
-
- // Scale for x, y based on data domains
- // origin: bottom, left
- var x_scale = d3.scale.linear()
- .domain([ xMin, xMax ])
- .range([ 0, WIDTH ]),
- y_scale = d3.scale.linear()
- .domain([ yMin, yMax ])
- .range([ HEIGHT, 0 ]);
-
- // Selection of SVG, append group (will group our entire chart), give attributes
- // apply a group and transform all coords away from margins
- var chart = d3.select( ".chart" ).append( "svg:g" )
- .attr( "class", "content" )
- .attr( "transform", translateStr( MARGIN, MARGIN ) );
-
- // axes
- var xAxisFn = d3.svg.axis()
- .scale( x_scale )
- .ticks( X_TICKS )
- .orient( 'bottom' );
- var xAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'x-axis' )
- .attr( 'transform', translateStr( 0, HEIGHT ) )
- .call( xAxisFn )
- //console.debug( 'xAxis:', xAxis ); window.xAxis = xAxis, window.xAxisFn = xAxisFn;
-
- var xAxisLabel = xAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'x-axis-label' )
- .attr( 'x', WIDTH / 2 )
- .attr( 'y', X_AXIS_LABEL_BUMP_Y )
- .attr( 'text-anchor', 'middle' )
- .text( xLabel );
- //console.debug( 'xAxisLabel:', xAxisLabel ); window.xAxisLabel = xAxisLabel;
-
- var yAxisFn = d3.svg.axis()
- .scale( y_scale )
- .ticks( Y_TICKS )
- .orient( 'left' );
- var yAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'y-axis' )
- .call( yAxisFn );
- //console.debug( 'yAxis:', yAxis ); window.yAxis = yAxis, window.yAxisFn = yAxisFn;
-
- var yAxisLabel = yAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'y-axis-label' )
- .attr( 'x', Y_AXIS_LABEL_BUMP_X )
- .attr( 'y', HEIGHT / 2 )
- .attr( 'text-anchor', 'middle' )
- .attr( 'transform', rotateStr( -90, Y_AXIS_LABEL_BUMP_X, HEIGHT / 2 ) )
- .text( yLabel );
- //console.debug( 'yAxisLabel:', yAxisLabel ); window.yAxisLabel = yAxisLabel;
-
- // grid lines
- var hGridLines = chart.selectAll( '.h-grid-line' )
- .data( x_scale.ticks( xAxisFn.ticks()[0] ) )
- .enter().append( 'svg:line' )
- .classed( 'grid-line h-grid-line', true )
- .attr( 'x1', x_scale ).attr( 'y1', 0 )
- .attr( 'x2', x_scale ).attr( 'y2', HEIGHT )
- //console.debug( 'hGridLines:', hGridLines ); window.hGridLines = hGridLines;
-
- var vGridLines = chart.selectAll( '.v-grid-line' )
- .data( y_scale.ticks( yAxisFn.ticks()[0] ) )
- .enter().append( 'svg:line' )
- .classed( 'grid-line v-grid-line', true )
- .attr( 'x1', 0 ) .attr( 'y1', y_scale )
- .attr( 'x2', WIDTH ).attr( 'y2', y_scale )
- //console.debug( 'vGridLines:', vGridLines ); window.vGridLines = vGridLines;
-
- // Functions used to render plot.
- var xPosFn = function( d, i ){
- return x_scale( col1_data[ i ] );
- };
- var yPosFn = function( d, i ){
- return y_scale( col2_data[ i ] );
- };
-
- // Create bubbles for each data point.
- chart.selectAll( "circle.bubble" )
- .data(data).enter()
- .append( "svg:circle" ).attr( "class", "bubble" )
- // start all bubbles at corner...
- .attr( "r", 0 )
- .attr( "fill", "white" )
- // ...animate to final position
- .transition().duration( ENTRY_ANIM_DURATION )
- .attr("cx", xPosFn )
- .attr("cy", yPosFn )
- .attr("r", BUBBLE_RADIUS);
-
- //TODO: on hover red line to axes, display values
+ var settingsForm = new ScatterplotView({
+ dataset : hda,
+ el : $( '#chart-settings-form' ),
+ apiDatasetsURL : apiDatasetsURL,
+ chartConfig : {
+ containerSelector : '#chart-holder',
+ marginTop : 20,
+ }
+ }).render();
});
</script></%def><%def name="body()">
- <h1 class="title">Scatterplot of '${title}':</h1>
- <h2 class="subtitle">${subtitle}</h2>
-
+ <h2 class="title">Scatterplot of '${hda['name']}'</h2>
+ <p class="subtitle">${hda['misc_info']}</p>
+ <div id="chart-holder"></div>
+ <div id="chart-settings-form"></div></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/63a8fb1d8e2b/
changeset: 63a8fb1d8e2b
user: jgoecks
date: 2012-09-21 20:05:37
summary: Small additions based on bdd35af2a18a
affected #: 2 files
diff -r bdd35af2a18afde11396fcf919b5fb4cacc986ff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -30,7 +30,8 @@
def get_data_provider( self, trans, name=None, source='data', raw=False, original_dataset=None ):
"""
- Returns data provider class by name and/or original dataset.
+ Returns data provider matching parameter values. For standalone data
+ sources, source parameter is ignored.
"""
data_provider = None
diff -r bdd35af2a18afde11396fcf919b5fb4cacc986ff -r 63a8fb1d8e2b8a8da71a5b618ef65981ff5c4ac3 lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -756,15 +756,9 @@
# Get dataset and indexed datatype.
dataset = self.get_hda_or_ldda( trans, track[ 'hda_ldda'], track[ 'dataset_id' ] )
data_sources = dataset.get_datasources( trans )
- data_provider_registry = trans.app.data_provider_registry
- if 'data_standalone' in data_sources:
- indexed_type = data_sources['data_standalone']['name']
- data_provider = data_provider_registry.get_data_provider( indexed_type )( dataset )
- else:
- indexed_type = data_sources['index']['name']
- # Get converted dataset and append track's genome data.
- converted_dataset = dataset.get_converted_dataset( trans, indexed_type )
- data_provider = data_provider_registry.get_data_provider( indexed_type )( converted_dataset, dataset )
+ data_provider = trans.app.data_provider_registry.get_data_provider( trans,
+ original_dataset=dataset,
+ source='index' )
# HACK: pass in additional params, which are only used for summary tree data, not BBI data.
track[ 'genome_wide_data' ] = { 'data': data_provider.get_genome_data( chroms_info, level=4, detail_cutoff=0, draw_cutoff=0 ) }
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Viz framework: (a) push data provider creation to registry to simplify provider creation; (b) fix bugs in filters module naming; (c) enable deeper sampling in BBI data provider.
by Bitbucket 21 Sep '12
by Bitbucket 21 Sep '12
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/bdd35af2a18a/
changeset: bdd35af2a18a
user: jgoecks
date: 2012-09-21 20:00:09
summary: Viz framework: (a) push data provider creation to registry to simplify provider creation; (b) fix bugs in filters module naming; (c) enable deeper sampling in BBI data provider.
affected #: 8 files
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/visualization/data_providers/basic.py
--- a/lib/galaxy/visualization/data_providers/basic.py
+++ b/lib/galaxy/visualization/data_providers/basic.py
@@ -100,62 +100,3 @@
f.close()
return data
-
-class DataProviderRegistry( object ):
- """
- Registry for data providers that enables listing and lookup.
- """
-
- def __init__( self ):
- # Mapping from dataset type name to a class that can fetch data from a file of that
- # 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.
- self.dataset_type_name_to_data_provider = {
- "tabix": {
- Vcf: VcfTabixDataProvider,
- Bed: BedTabixDataProvider,
- Gtf: GtfTabixDataProvider,
- ENCODEPeak: ENCODEPeakTabixDataProvider,
- Interval: IntervalTabixDataProvider,
- ChromatinInteractions: ChromatinInteractionsTabixDataProvider,
- "default" : TabixDataProvider
- },
- "interval_index": IntervalIndexDataProvider,
- "bai": BamDataProvider,
- "bam": SamDataProvider,
- "summary_tree": SummaryTreeDataProvider,
- "bigwig": BigWigDataProvider,
- "bigbed": BigBedDataProvider
- }
-
- def get_data_provider( name=None, original_dataset=None ):
- """
- Returns data provider class by name and/or original dataset.
- """
- data_provider = None
- if name:
- value = dataset_type_name_to_data_provider[ name ]
- if isinstance( value, dict ):
- # Get converter by dataset extension; if there is no data provider,
- # get the default.
- data_provider = value.get( original_dataset.datatype.__class__, value.get( "default" ) )
- else:
- data_provider = value
- elif original_dataset:
- # Look up data provider from datatype's informaton.
- try:
- # Get data provider mapping and data provider for 'data'. If
- # provider available, use it; otherwise use generic provider.
- _ , data_provider_mapping = original_dataset.datatype.get_track_type()
- if 'data_standalone' in data_provider_mapping:
- data_provider_name = data_provider_mapping[ 'data_standalone' ]
- else:
- data_provider_name = data_provider_mapping[ 'data' ]
- if data_provider_name:
- data_provider = self.get_data_provider( name=data_provider_name, original_dataset=original_dataset )
- else:
- data_provider = GenomeDataProvider
- except:
- pass
- return data_provider
-
\ No newline at end of file
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -112,6 +112,8 @@
class GenomeDataProvider( BaseDataProvider ):
""" Base class for genome data providers. """
+
+ data_type = None
"""
Mapping from column name to payload data; this mapping is used to create
@@ -314,6 +316,8 @@
class TabixDataProvider( FilterableMixin, GenomeDataProvider ):
+ data_type = 'tabix'
+
"""
Tabix index data provider for the Galaxy track browser.
"""
@@ -354,8 +358,10 @@
#
class IntervalDataProvider( GenomeDataProvider ):
+ data_type = 'interval_index'
+
"""
- Processes BED data from native format to payload format.
+ Processes interval data from native format to payload format.
Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
"""
@@ -437,6 +443,8 @@
Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
"""
+
+ data_type = 'interval_index'
def get_iterator( self, chrom, start, end ):
raise Exception( "Unimplemented Method" )
@@ -533,6 +541,8 @@
for large datasets.
"""
+ data_type = 'interval_index'
+
def get_iterator( self, chrom=None, start=None, end=None ):
# Read first line in order to match chrom naming format.
line = source.readline()
@@ -570,6 +580,8 @@
"""
col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } }
+
+ data_type = 'bai'
def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
"""
@@ -675,6 +687,8 @@
for large datasets.
"""
+ data_type = 'tabix'
+
def get_iterator( self, chrom, start, end ):
# Read first line in order to match chrom naming format.
line = source.readline()
@@ -706,6 +720,8 @@
"""
Summary tree data provider for the Galaxy track browser.
"""
+
+ data_type = 'summary_tree'
CACHE = LRUCache( 20 ) # Store 20 recently accessed indices for performance
@@ -771,6 +787,8 @@
Provides access to intervals from a sorted indexed BAM file. Position data
is reported in 1-based, closed format, i.e. SAM/BAM format.
"""
+
+ data_type = 'bai'
def get_filters( self ):
"""
@@ -951,6 +969,8 @@
return { 'data': results, 'message': message, 'max_low': max_low, 'max_high': max_high }
class SamDataProvider( BamDataProvider ):
+
+ data_type = 'bai'
def __init__( self, converted_dataset=None, original_dataset=None, dependencies=None ):
""" Create SamDataProvider. """
@@ -966,6 +986,9 @@
"""
BBI data provider for the Galaxy track browser.
"""
+
+ data_type = 'bigwig'
+
def valid_chroms( self ):
# No way to return this info as of now
return None
@@ -976,7 +999,7 @@
f.close()
return all_dat is not None
- def get_data( self, chrom, start, end, start_val=0, max_vals=None, **kwargs ):
+ def get_data( self, chrom, start, end, start_val=0, max_vals=None, num_samples=1000, **kwargs ):
# Bigwig can be a standalone bigwig file, in which case we use
# original_dataset, or coming from wig->bigwig conversion in
# which we use converted_dataset
@@ -1009,14 +1032,11 @@
return dict( data=dict( min=min, max=max, mean=mean, sd=sd ) )
- # Sample from region using approximately this many samples.
- N = 1000
-
def summarize_region( bbi, chrom, start, end, num_points ):
'''
Returns results from summarizing a region using num_points.
NOTE: num_points cannot be greater than end - start or BBI
- will return None for all positions.s
+ will return None for all positions.
'''
result = []
@@ -1042,7 +1062,8 @@
return result
# Approach is different depending on region size.
- if end - start < N:
+ num_samples = int( num_samples )
+ if end - start < num_samples:
# Get values for individual bases in region, including start and end.
# To do this, need to increase end to next base and request number of points.
num_points = end - start + 1
@@ -1050,10 +1071,10 @@
else:
#
# The goal is to sample the region between start and end uniformly
- # using ~N data points. The challenge is that the size of sampled
- # intervals rarely is full bases, so sampling using N points will
- # leave the end of the region unsampled due to remainders for each
- # interval. To recitify this, a new N is calculated based on the
+ # using ~N (num_samples) data points. The challenge is that the size of
+ # sampled intervals rarely is full bases, so sampling using N points
+ # will leave the end of the region unsampled due to remainders for
+ # each interval. To recitify this, a new N is calculated based on the
# step size that covers as much of the region as possible.
#
# However, this still leaves some of the region unsampled. This
@@ -1063,7 +1084,7 @@
#
# Start with N samples.
- num_points = N
+ num_points = num_samples
step_size = ( end - start ) / num_points
# Add additional points to sample in the remainder not covered by
# the initial N samples.
@@ -1100,6 +1121,8 @@
Interval index files used only for GFF files.
"""
col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
+
+ data_type = 'interval_index'
def write_data_to_file( self, regions, filename ):
source = open( self.original_dataset.file_name )
@@ -1177,6 +1200,8 @@
NOTE: this data provider does not use indices, and hence will be very slow
for large datasets.
"""
+
+ data_type = 'interval_index'
def get_iterator( self, chrom, start, end ):
"""
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -28,46 +28,63 @@
"bigbed": BigBedDataProvider
}
- def get_data_provider( self, name=None, raw=False, original_dataset=None ):
+ def get_data_provider( self, trans, name=None, source='data', raw=False, original_dataset=None ):
"""
Returns data provider class by name and/or original dataset.
"""
- # If getting raw data, use original dataset type to get data provider.
+ data_provider = None
if raw:
+ # Working with raw data.
if isinstance( original_dataset.datatype, Gff ):
- return RawGFFDataProvider
+ data_provider_class = RawGFFDataProvider
elif isinstance( original_dataset.datatype, Bed ):
- return RawBedDataProvider
+ data_provider_class = RawBedDataProvider
elif isinstance( original_dataset.datatype, Vcf ):
- return RawVcfDataProvider
+ data_provider_class = RawVcfDataProvider
elif isinstance( original_dataset.datatype, Tabular ):
- return ColumnDataProvider
+ data_provider_class = ColumnDataProvider
- # Using converted dataset, so get corrsponding data provider.
- data_provider = None
- if name:
- value = self.dataset_type_name_to_data_provider[ name ]
- if isinstance( value, dict ):
- # Get converter by dataset extension; if there is no data provider,
- # get the default.
- data_provider = value.get( original_dataset.datatype.__class__, value.get( "default" ) )
- else:
- data_provider = value
- elif original_dataset:
- # Look up data provider from datatype's informaton.
- try:
- # Get data provider mapping and data provider for 'data'. If
- # provider available, use it; otherwise use generic provider.
+ data_provider = data_provider_class( original_dataset=original_dataset )
+
+ else:
+ # Working with converted or standalone dataset.
+
+ if name:
+ # Provider requested by name; get from mappings.
+ value = self.dataset_type_name_to_data_provider[ name ]
+ if isinstance( value, dict ):
+ # Get converter by dataset extension; if there is no data provider,
+ # get the default.
+ data_provider_class = value.get( original_dataset.datatype.__class__, value.get( "default" ) )
+ else:
+ data_provider_class = value
+
+ # If name is the same as original dataset's type, dataset is standalone.
+ # Otherwise, a converted dataset is being used.
+ if name == original_dataset.ext:
+ data_provider = data_provider_class( original_dataset=original_dataset )
+ else:
+ converted_dataset = original_dataset.get_converted_dataset( trans, name )
+ deps = original_dataset.get_converted_dataset_deps( trans, name )
+ data_provider = data_provider_class( original_dataset=original_dataset,
+ converted_dataset=converted_dataset,
+ dependencies=deps )
+
+ elif original_dataset:
+ # No name, so look up a provider name from datatype's information.
+
+ # Dataset must have get_track_type function to get data.
+ if not hasattr( original_dataset.datatype, 'get_track_type'):
+ return None
+
+ # Get data provider mapping and data provider.
_ , data_provider_mapping = original_dataset.datatype.get_track_type()
if 'data_standalone' in data_provider_mapping:
data_provider_name = data_provider_mapping[ 'data_standalone' ]
else:
- data_provider_name = data_provider_mapping[ 'data' ]
- if data_provider_name:
- data_provider = self.get_data_provider( name=data_provider_name, original_dataset=original_dataset )
- else:
- data_provider = GenomeDataProvider
- except:
- pass
+ data_provider_name = data_provider_mapping[ source ]
+
+ data_provider = self.get_data_provider( trans, name=data_provider_name, original_dataset=original_dataset )
+
return data_provider
\ No newline at end of file
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/web/api/datasets.py
--- a/lib/galaxy/web/api/datasets.py
+++ b/lib/galaxy/web/api/datasets.py
@@ -86,28 +86,14 @@
if msg:
return msg
- # NOTE: finding valid chroms is prohibitive for large summary trees and is not currently used by
- # the client.
- valid_chroms = None
# Check for data in the genome window.
data_provider_registry = trans.app.data_provider_registry
- if data_sources.get( 'index' ):
- tracks_dataset_type = data_sources['index']['name']
- converted_dataset = dataset.get_converted_dataset( trans, tracks_dataset_type )
- indexer = data_provider_registry.get_data_provider( tracks_dataset_type )( converted_dataset, dataset )
- if not indexer.has_data( chrom ):
- return messages.NO_DATA
- #valid_chroms = indexer.valid_chroms()
- else:
- # Standalone data provider
- standalone_provider = data_provider_registry.get_data_provider( data_sources['data_standalone']['name'] )( dataset )
- kwargs = {"stats": True}
- if not standalone_provider.has_data( chrom ):
- return messages.NO_DATA
- #valid_chroms = standalone_provider.valid_chroms()
+ data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset= dataset, source='index' )
+ if not data_provider.has_data( chrom ):
+ return messages.NO_DATA
# Have data if we get here
- return { "status": messages.DATA, "valid_chroms": valid_chroms }
+ return { "status": messages.DATA, "valid_chroms": None }
def _search_features( self, trans, dataset, query ):
"""
@@ -151,45 +137,32 @@
data_provider_registry = trans.app.data_provider_registry
if mode == "Coverage":
# Get summary using minimal cutoffs.
- tracks_dataset_type = data_sources['index']['name']
- converted_dataset = dataset.get_converted_dataset( trans, tracks_dataset_type )
- indexer = data_provider_registry.get_data_provider( tracks_dataset_type )( converted_dataset, dataset )
+ indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], detail_cutoff=0, draw_cutoff=0 )
if summary == "detail":
# Use maximum level of detail--2--to get summary data no matter the resolution.
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], level=2, detail_cutoff=0, draw_cutoff=0 )
frequencies, max_v, avg_v, delta = summary
- return { 'dataset_type': tracks_dataset_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
+ return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and mode == "Auto":
# Only check for summary_tree if it's Auto mode (which is the default)
#
# Have to choose between indexer and data provider
- tracks_dataset_type = data_sources['index']['name']
- converted_dataset = dataset.get_converted_dataset( trans, tracks_dataset_type )
- indexer = data_provider_registry.get_data_provider( tracks_dataset_type )( converted_dataset, dataset )
+ indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ] )
if summary is None:
- return { 'dataset_type': tracks_dataset_type, 'data': None }
+ return { 'dataset_type': indexer.data_type, 'data': None }
if summary == "draw":
kwargs["no_detail"] = True # meh
extra_info = "no_detail"
elif summary != "detail":
frequencies, max_v, avg_v, delta = summary
- return { 'dataset_type': tracks_dataset_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
+ return { 'dataset_type': indexer.data_type, 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
# Get data provider.
- if "data_standalone" in data_sources:
- tracks_dataset_type = data_sources['data_standalone']['name']
- data_provider_class = data_provider_registry.get_data_provider( name=tracks_dataset_type, original_dataset=dataset )
- data_provider = data_provider_class( original_dataset=dataset )
- else:
- tracks_dataset_type = data_sources['data']['name']
- data_provider_class = data_provider_registry.get_data_provider( name=tracks_dataset_type, original_dataset=dataset )
- converted_dataset = dataset.get_converted_dataset( trans, tracks_dataset_type )
- deps = dataset.get_converted_dataset_deps( trans, tracks_dataset_type )
- data_provider = data_provider_class( converted_dataset=converted_dataset, original_dataset=dataset, dependencies=deps )
+ data_provider = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='data' )
# Allow max_vals top be data provider set if not passed
if max_vals is None:
@@ -197,7 +170,7 @@
# Get and return data from data_provider.
result = data_provider.get_data( chrom, int( low ), int( high ), int( start_val ), int( max_vals ), **kwargs )
- result.update( { 'dataset_type': tracks_dataset_type, 'extra_info': extra_info } )
+ result.update( { 'dataset_type': data_provider.data_type, 'extra_info': extra_info } )
return result
def _raw_data( self, trans, dataset, **kwargs ):
@@ -214,7 +187,7 @@
# Return data.
data = None
- data_provider = trans.app.data_provider_registry.get_data_provider( raw=True, original_dataset=dataset )
+ data_provider = trans.app.data_provider_registry.get_data_provider( trans, raw=True, original_dataset=dataset )
if data_provider == ColumnDataProvider:
#pre: should have column kwargs
@@ -222,13 +195,13 @@
#TODO??: could default to first two here
assert 'cols' in kwargs, (
"ColumnDataProvider needs a 'cols' parameter in the query string" )
- data = data_provider( original_dataset=dataset ).get_data( **kwargs )
+ data = data_provider.get_data( **kwargs )
else:
# Default to genomic data.
# FIXME: need better way to set dataset_type.
low, high = int( kwargs.get( 'low' ) ), int( kwargs.get( 'high' ) )
- data = data_provider( original_dataset=dataset ).get_data( start=low, end=high, **kwargs )
+ data = data_provider.get_data( start=low, end=high, **kwargs )
data[ 'dataset_type' ] = 'interval_index'
data[ 'extra_info' ] = None
if isinstance( dataset.datatype, Vcf ):
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -204,15 +204,12 @@
if run_on_regions:
for jida in original_job.input_datasets:
input_dataset = jida.dataset
- if data_provider_registry.get_data_provider( original_dataset=input_dataset ):
- # Can index dataset.
- track_type, data_sources = input_dataset.datatype.get_track_type()
- # Convert to datasource that provides 'data' because we need to
- # extract the original data.
- data_source = data_sources[ 'data' ]
- msg = self.convert_dataset( trans, input_dataset, data_source )
- if msg is not None:
- messages_list.append( msg )
+ data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data' )
+ if data_provider:
+ if not data_provider.converted_dataset:
+ msg = self.convert_dataset( trans, input_dataset, data_source )
+ if msg is not None:
+ messages_list.append( msg )
# Return any messages generated during conversions.
return_message = get_highest_priority_msg( messages_list )
@@ -326,10 +323,7 @@
trans.app.security_agent.set_all_dataset_permissions( new_dataset.dataset, hda_permissions )
# Write subset of data to new dataset
- data_provider_class = data_provider_registry.get_data_provider( original_dataset=input_dataset )
- data_provider = data_provider_class( original_dataset=input_dataset,
- converted_dataset=converted_dataset,
- dependencies=deps )
+ data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data' )
trans.app.object_store.create( new_dataset.dataset )
data_provider.write_data_to_file( regions, new_dataset.file_name )
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -460,8 +460,9 @@
prefs = {}
track_type, _ = dataset.datatype.get_track_type()
- track_data_provider_class = trans.app.data_provider_registry.get_data_provider( original_dataset=dataset )
- track_data_provider = track_data_provider_class( original_dataset=dataset )
+ track_data_provider = trans.app.data_provider_registry.get_data_provider( trans,
+ original_dataset=dataset,
+ source='data' )
return {
"track_type": track_type,
@@ -536,8 +537,8 @@
"""
# Get data provider.
track_type, _ = dataset.datatype.get_track_type()
- track_data_provider_class = trans.app.data_provider_registry.get_data_provider( original_dataset=dataset )
- track_data_provider = track_data_provider_class( original_dataset=dataset )
+ track_data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset=dataset )
+
if isinstance( dataset, trans.app.model.HistoryDatasetAssociation ):
hda_ldda = "hda"
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff static/scripts/viz/trackster/filters.js
--- a/static/scripts/viz/trackster/filters.js
+++ b/static/scripts/viz/trackster/filters.js
@@ -617,7 +617,8 @@
});
return {
- FiltersManager: FiltersManager
+ FiltersManager: FiltersManager,
+ NumberFilter: NumberFilter
};
});
diff -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 -r bdd35af2a18afde11396fcf919b5fb4cacc986ff static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1,7 +1,7 @@
define( ["libs/underscore", "viz/visualization", "viz/trackster/util",
"viz/trackster/slotting", "viz/trackster/painters", "mvc/data",
"viz/trackster/filters" ],
- function( _, visualization, util, slotting, painters, data, filters ) {
+ function( _, visualization, util, slotting, painters, data, filters_mod ) {
var extend = _.extend;
var get_random_color = util.get_random_color;
@@ -587,7 +587,7 @@
moveable(this.container_div, this.drag_handle_class, ".group", this);
// Set up filters.
- this.filters_manager = new filters.FiltersManager(this);
+ this.filters_manager = new filters_mod.FiltersManager(this);
this.header_div.after(this.filters_manager.parent_div);
// For saving drawables' filter managers when group-level filtering is done:
this.saved_filters_managers = [];
@@ -601,7 +601,7 @@
if ('filters' in obj_dict) {
// FIXME: Pass collection_dict to DrawableCollection/Drawable will make this easier.
var old_manager = this.filters_manager;
- this.filters_manager = new filters.FiltersManager(this, obj_dict.filters);
+ this.filters_manager = new filters_mod.FiltersManager(this, obj_dict.filters);
old_manager.parent_div.replaceWith(this.filters_manager.parent_div);
if (obj_dict.filters.visible) {
@@ -761,7 +761,7 @@
if (filters.length === num_feature_tracks) {
// Add new filter.
// FIXME: can filter.copy() be used?
- new_filter = new NumberFilter( {
+ new_filter = new filters_mod.NumberFilter( {
name: filters[0].name,
index: filters[0].index
} );
@@ -2612,7 +2612,7 @@
moveable(track.container_div, track.drag_handle_class, ".group", track);
// Attribute init.
- this.filters_manager = new filters.FiltersManager(this, ('filters' in obj_dict ? obj_dict.filters : null));
+ this.filters_manager = new filters_mod.FiltersManager(this, ('filters' in obj_dict ? obj_dict.filters : null));
// HACK: set filters manager for data manager.
// FIXME: prolly need function to set filters and update data_manager reference.
this.data_manager.set('filters_manager', this.filters_manager);
@@ -4188,7 +4188,6 @@
}
};
-// Exports
return {
View: View,
DrawableGroup: DrawableGroup,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Push data sources/converter methods from controller mixin to dataset object.
by Bitbucket 21 Sep '12
by Bitbucket 21 Sep '12
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/8a8dcc0d3668/
changeset: 8a8dcc0d3668
user: jgoecks
date: 2012-09-21 17:52:47
summary: Push data sources/converter methods from controller mixin to dataset object.
affected #: 4 files
diff -r c56a600064a4add89de1c970e99983ae438b8db2 -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1248,6 +1248,56 @@
def get_visualizations( self ):
return self.datatype.get_visualizations( self )
+ def get_datasources( self, trans ):
+ """
+ Returns datasources for dataset; if datasources are not available
+ due to indexing, indexing is started. Return value is a dictionary
+ with entries of type
+ (<datasource_type> : {<datasource_name>, <indexing_message>}).
+ """
+ track_type, data_sources = self.datatype.get_track_type()
+ data_sources_dict = {}
+ msg = None
+ for source_type, data_source in data_sources.iteritems():
+ if source_type == "data_standalone":
+ # Nothing to do.
+ msg = None
+ else:
+ # Convert.
+ msg = self.convert_dataset( trans, data_source )
+
+ # Store msg.
+ data_sources_dict[ source_type ] = { "name" : data_source, "message": msg }
+
+ return data_sources_dict
+
+ def convert_dataset( self, trans, target_type ):
+ """
+ Converts a dataset to the target_type and returns a message indicating
+ status of the conversion. None is returned to indicate that dataset
+ was converted successfully.
+ """
+
+ # Get converted dataset; this will start the conversion if necessary.
+ try:
+ converted_dataset = self.get_converted_dataset( trans, target_type )
+ except NoConverterException:
+ return messages.NO_CONVERTER
+ except ConverterDependencyException, dep_error:
+ return { 'kind': messages.ERROR, 'message': dep_error.value }
+
+ # Check dataset state and return any messages.
+ msg = None
+ if converted_dataset and converted_dataset.state == trans.app.model.Dataset.states.ERROR:
+ job_id = trans.sa_session.query( trans.app.model.JobToOutputDatasetAssociation ) \
+ .filter_by( dataset_id=converted_dataset.id ).first().job_id
+ job = trans.sa_session.query( trans.app.model.Job ).get( job_id )
+ msg = { 'kind': messages.ERROR, 'message': job.stderr }
+ elif not converted_dataset or converted_dataset.state != trans.app.model.Dataset.states.OK:
+ msg = messages.PENDING
+
+ return msg
+
class HistoryDatasetAssociation( DatasetInstance ):
def __init__( self,
hid = None,
diff -r c56a600064a4add89de1c970e99983ae438b8db2 -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 lib/galaxy/web/api/datasets.py
--- a/lib/galaxy/web/api/datasets.py
+++ b/lib/galaxy/web/api/datasets.py
@@ -80,7 +80,7 @@
return msg
# Get datasources and check for messages.
- data_sources = self._get_datasources( trans, dataset )
+ data_sources = dataset.get_datasources( trans )
messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
msg = get_highest_priority_msg( messages_list )
if msg:
@@ -139,7 +139,7 @@
return msg
# Get datasources and check for messages.
- data_sources = self._get_datasources( trans, dataset )
+ data_sources = dataset.get_datasources( trans )
messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
return_message = get_highest_priority_msg( messages_list )
if return_message:
diff -r c56a600064a4add89de1c970e99983ae438b8db2 -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -312,33 +312,6 @@
if dataset.state != trans.app.model.Job.states.OK:
return messages.PENDING
return None
-
- def convert_dataset( self, trans, dataset, target_type ):
- """
- Converts a dataset to the target_type and returns a message indicating
- status of the conversion. None is returned to indicate that dataset
- was converted successfully.
- """
-
- # Get converted dataset; this will start the conversion if necessary.
- try:
- converted_dataset = dataset.get_converted_dataset( trans, target_type )
- except NoConverterException:
- return messages.NO_CONVERTER
- except ConverterDependencyException, dep_error:
- return { 'kind': messages.ERROR, 'message': dep_error.value }
-
- # Check dataset state and return any messages.
- msg = None
- if converted_dataset and converted_dataset.state == trans.app.model.Dataset.states.ERROR:
- job_id = trans.sa_session.query( trans.app.model.JobToOutputDatasetAssociation ) \
- .filter_by( dataset_id=converted_dataset.id ).first().job_id
- job = trans.sa_session.query( trans.app.model.Job ).get( job_id )
- msg = { 'kind': messages.ERROR, 'message': job.stderr }
- elif not converted_dataset or converted_dataset.state != trans.app.model.Dataset.states.OK:
- msg = messages.PENDING
-
- return msg
class UsesLibraryMixin:
@@ -625,29 +598,6 @@
return visualization
- def _get_datasources( self, trans, dataset ):
- """
- Returns datasources for dataset; if datasources are not available
- due to indexing, indexing is started. Return value is a dictionary
- with entries of type
- (<datasource_type> : {<datasource_name>, <indexing_message>}).
- """
- track_type, data_sources = dataset.datatype.get_track_type()
- data_sources_dict = {}
- msg = None
- for source_type, data_source in data_sources.iteritems():
- if source_type == "data_standalone":
- # Nothing to do.
- msg = None
- else:
- # Convert.
- msg = self.convert_dataset( trans, dataset, data_source )
-
- # Store msg.
- data_sources_dict[ source_type ] = { "name" : data_source, "message": msg }
-
- return data_sources_dict
-
class UsesStoredWorkflowMixin( SharableItemSecurityMixin ):
""" Mixin for controllers that use StoredWorkflow objects. """
def get_stored_workflow( self, trans, id, check_ownership=True, check_accessible=False ):
diff -r c56a600064a4add89de1c970e99983ae438b8db2 -r 8a8dcc0d36687fcfaaa1ae26e136e76b4a0d7bb0 lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -755,7 +755,7 @@
for track in tracks:
# Get dataset and indexed datatype.
dataset = self.get_hda_or_ldda( trans, track[ 'hda_ldda'], track[ 'dataset_id' ] )
- data_sources = self._get_datasources( trans, dataset )
+ data_sources = dataset.get_datasources( trans )
data_provider_registry = trans.app.data_provider_registry
if 'data_standalone' in data_sources:
indexed_type = data_sources['data_standalone']['name']
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Add the ability to review tools migration stages that are available for the current Galaxy instance.
by Bitbucket 21 Sep '12
by Bitbucket 21 Sep '12
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/c56a600064a4/
changeset: c56a600064a4
user: greg
date: 2012-09-21 17:21:38
summary: Add the ability to review tools migration stages that are available for the current Galaxy instance.
affected #: 4 files
diff -r cd739bd3dca4859fecfe499fc976b0e0b6478238 -r c56a600064a4add89de1c970e99983ae438b8db2 lib/galaxy/tool_shed/migrate/versions/0004_tools.py
--- a/lib/galaxy/tool_shed/migrate/versions/0004_tools.py
+++ b/lib/galaxy/tool_shed/migrate/versions/0004_tools.py
@@ -1,9 +1,9 @@
"""
The NCBI BLAST+ tools have been eliminated from the distribution. The tools and
-datatypes are are now available in repositories named ncbi_blast_plus and
-blast_datatypes, respectively, from the main Galaxy tool shed at
-http://toolshed.g2.bx.psu.edu will be installed into your local Galaxy instance
-at the location discussed above by running the following command.
+datatypes are now available in repositories named ncbi_blast_plus and
+blast_datatypes, in the main Galaxy tool shed at http://toolshed.g2.bx.psu.edu.
+These repositories will be installed into your local Galaxy instance at the
+location discussed above by running the following command.
"""
import sys
diff -r cd739bd3dca4859fecfe499fc976b0e0b6478238 -r c56a600064a4add89de1c970e99983ae438b8db2 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py
+++ b/lib/galaxy/web/controllers/admin.py
@@ -8,8 +8,10 @@
from galaxy.actions.admin import AdminActions
from galaxy.web.params import QuotaParamParser
from galaxy.exceptions import *
+from galaxy.util.odict import *
+from galaxy.tool_shed.encoding_util import *
import galaxy.datatypes.registry
-import logging
+import logging, imp, subprocess, urllib2
log = logging.getLogger( __name__ )
@@ -685,6 +687,75 @@
if emails is None:
emails = [ u.email for u in trans.sa_session.query( trans.app.model.User ).enable_eagerloads( False ).all() ]
return trans.fill_template( 'admin/impersonate.mako', emails=emails, message=message, status=status )
+ def get_tool_shed_url_from_tools_xml_file_path( self, trans, tool_shed ):
+ search_str = '://%s' % tool_shed
+ for shed_name, shed_url in trans.app.tool_shed_registry.tool_sheds.items():
+ if shed_url.find( search_str ) >= 0:
+ if shed_url.endswith( '/' ):
+ shed_url = shed_url.rstrip( '/' )
+ return shed_url
+ return None
+ def check_for_tool_dependencies( self, trans, migration_stage ):
+ # Get the 000x_tools.xml file associated with migration_stage.
+ tools_xml_file_path = os.path.abspath( os.path.join( trans.app.config.root, 'scripts', 'migrate_tools', '%04d_tools.xml' % migration_stage ) )
+ tree = util.parse_xml( tools_xml_file_path )
+ root = tree.getroot()
+ tool_shed = root.get( 'name' )
+ tool_shed_url = self.get_tool_shed_url_from_tools_xml_file_path( trans, tool_shed )
+ repo_name_dependency_tups = []
+ if tool_shed_url:
+ for elem in root:
+ if elem.tag == 'repository':
+ tool_dependencies = []
+ tool_dependencies_dict = {}
+ repository_name = elem.get( 'name' )
+ changeset_revision = elem.get( 'changeset_revision' )
+ url = '%s/repository/get_tool_dependencies?name=%s&owner=devteam&changeset_revision=%s&webapp=install_manager' % \
+ ( tool_shed_url, repository_name, changeset_revision )
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ if text:
+ tool_dependencies_dict = tool_shed_decode( text )
+ for dependency_key, requirements_dict in tool_dependencies_dict.items():
+ tool_dependency_name = requirements_dict[ 'name' ]
+ tool_dependency_version = requirements_dict[ 'version' ]
+ tool_dependency_type = requirements_dict[ 'type' ]
+ tool_dependency_readme = requirements_dict.get( 'readme', '' )
+ tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type, tool_dependency_readme ) )
+ repo_name_dependency_tups.append( ( repository_name, tool_dependencies ) )
+ return repo_name_dependency_tups
+ @web.expose
+ @web.require_admin
+ def review_tool_migration_stages( self, trans, **kwd ):
+ message = util.restore_text( kwd.get( 'message', '' ) )
+ status = util.restore_text( kwd.get( 'status', 'done' ) )
+ migration_stages_dict = odict()
+ migration_modules = []
+ migration_scripts_dir = os.path.abspath( os.path.join( trans.app.config.root, 'lib', 'galaxy', 'tool_shed', 'migrate', 'versions' ) )
+ migration_scripts_dir_contents = os.listdir( migration_scripts_dir )
+ for item in migration_scripts_dir_contents:
+ if os.path.isfile( os.path.join( migration_scripts_dir, item ) ) and item.endswith( '.py' ):
+ module = item.replace( '.py', '' )
+ migration_modules.append( module )
+ if migration_modules:
+ migration_modules.sort()
+ # Remove the 0001_tools.py script since it is the seed.
+ migration_modules = migration_modules[ 1: ]
+ # Reverse the list so viewing will be newest to oldest.
+ migration_modules.reverse()
+ for migration_module in migration_modules:
+ migration_stage = int( migration_module.replace( '_tools', '' ) )
+ repo_name_dependency_tups = self.check_for_tool_dependencies( trans, migration_stage )
+ open_file_obj, file_name, description = imp.find_module( migration_module, [ migration_scripts_dir ] )
+ imported_module = imp.load_module( 'upgrade', open_file_obj, file_name, description )
+ migration_info = imported_module.__doc__
+ open_file_obj.close()
+ migration_stages_dict[ migration_stage ] = ( migration_info, repo_name_dependency_tups )
+ return trans.fill_template( 'admin/review_tool_migration_stages.mako',
+ migration_stages_dict=migration_stages_dict,
+ message=message,
+ status=status )
@web.expose
@web.require_admin
def view_datatypes_registry( self, trans, **kwd ):
diff -r cd739bd3dca4859fecfe499fc976b0e0b6478238 -r c56a600064a4add89de1c970e99983ae438b8db2 templates/admin/review_tool_migration_stages.mako
--- /dev/null
+++ b/templates/admin/review_tool_migration_stages.mako
@@ -0,0 +1,120 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Tool migrations that can be performed on this Galaxy instance</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <p>
+ The list of tool migration stages below, displayed most recent to oldest, provides information about the repositories in the
+ main Galaxy tool shed that will be cloned at each stage if you run the shell command for that stage. This enables you to execute
+ the migration process for any stage at any time.
+ </p>
+ <p>
+ Keep in mind that tools included in a repository that you want to be displayed in the Galaxy tool panel when the repository is
+ installed must be defined in the <b>tool_conf.xml</b> (or equivalent) config file prior to execution of the migration process for a
+ stage. Executing a migration process multiple times will have no affect unless the repositories associated with that stage have been
+ uninstalled prior to the execution of the migration process.
+ </p>
+ <p>
+ When you initiate a migration process, the associated repositories will be cloned from the Galaxy tool shed at
+ <a href="http://toolshed.g2.bx.psu.edu" target="_blank">http://toolshed.g2.bx.psu.edu</a>. The location in which the tool repositories
+ will be installed is the value of the 'tool_path' attribute in the <tool> tag of the file named ./migrated_tool_conf.xml
+ (i.e., <b><toolbox tool_path="../shed_tools"></b>). The default location setting is <b>'../shed_tools'</b>, which may be problematic
+ for some cluster environments, so make sure to change it before you execute the installation process if appropriate. The configured location
+ must be outside of the Galaxy installation directory or it must be in a sub-directory protected by a properly configured <b>.hgignore</b>
+ file if the directory is within the Galaxy installation directory hierarchy. This is because tool shed repositories will be installed using
+ mercurial's clone feature, which creates .hg directories and associated mercurial repository files. Not having <b>.hgignore</b> properly
+ configured could result in undesired behavior when modifying or updating your local Galaxy instance or the tool shed repositories if they are
+ in directories that pose conflicts. See mercurial's .hgignore documentation at
+ <a href="http://mercurial.selenic.com/wiki/.hgignore" target="_blank">http://mercurial.selenic.com/wiki/.hgignore</a> for details.
+ </p>
+ </div>
+ <table class="grid">
+ %for stage in migration_stages_dict.keys():
+ <%
+ migration_command = 'sh ./scripts/migrate_tools/%04d_tools.sh' % stage
+ install_dependencies = '%s install_dependencies' % migration_command
+ migration_tup = migration_stages_dict[ stage ]
+ migration_info, repo_name_dependency_tups = migration_tup
+ repository_names = []
+ for repo_name_dependency_tup in repo_name_dependency_tups:
+ repository_name, tool_dependencies = repo_name_dependency_tup
+ if repository_name not in repository_names:
+ repository_names.append( repository_name )
+ if repository_names:
+ repository_names.sort()
+ repository_names = ', '.join( repository_names )
+ %>
+ <tr><td bgcolor="#D8D8D8"><b>Tool migration stage ${stage} - repositories: ${repository_names}</b></td></tr>
+ <tr>
+ <td bgcolor="#FFFFCC">
+ <div class="form-row">
+ <p>${migration_info} <b>Run commands from the Galaxy installation directory!</b></p>
+ <p>
+ %if tool_dependencies:
+ This migration stage includes tools that have tool dependencies that can be automatically installed. To install them, run:<br/>
+ <b>${install_dependencies}</b><br/><br/>
+ To skip tool dependency installation run:<br/>
+ <b>${migration_command}</b>
+ %else:
+ <b>${migration_command}</b>
+ %endif
+ </p>
+ </div>
+ </td>
+ </tr>
+ %for repo_name_dependency_tup in repo_name_dependency_tups:
+ <% repository_name, tool_dependencies = repo_name_dependency_tup %>
+ <tr>
+ <td bgcolor="#DADFEF">
+ <div class="form-row">
+ <b>Repository:</b> ${repository_name}
+ </div>
+ </td>
+ </tr>
+ %if tool_dependencies:
+ <tr>
+ <td>
+ <div class="form-row">
+ <b>Tool dependencies</b>
+ </div>
+ </td>
+ </tr>
+ %for tool_dependencies_tup in tool_dependencies:
+ <%
+ tool_dependency_name = tool_dependencies_tup[0]
+ tool_dependency_version = tool_dependencies_tup[1]
+ tool_dependency_type = tool_dependencies_tup[2]
+ installation_requirements = tool_dependencies_tup[3].replace( '\n', '<br/>' )
+ %>
+ <tr>
+ <td>
+ <div class="form-row">
+ <b>Name:</b> ${tool_dependency_name} <b>Version:</b> ${tool_dependency_version} <b>Type:</b> ${tool_dependency_type}
+ </div>
+ <div class="form-row">
+ <b>Requirements and installation information:</b><br/>
+ ${installation_requirements}
+ </div>
+ </td>
+ </tr>
+ %endfor
+ %else:
+ <tr>
+ <td>
+ <div class="form-row">
+ No tool dependencies have been defined for this repository.
+ </div>
+ </td>
+ </tr>
+ %endif
+ %endfor
+ %endfor
+ </table>
+ </div>
+</div>
diff -r cd739bd3dca4859fecfe499fc976b0e0b6478238 -r c56a600064a4add89de1c970e99983ae438b8db2 templates/webapps/galaxy/admin/index.mako
--- a/templates/webapps/galaxy/admin/index.mako
+++ b/templates/webapps/galaxy/admin/index.mako
@@ -66,10 +66,11 @@
<div class="toolSectionBody"><div class="toolSectionBg"><div class="toolTitle"><a href="${h.url_for( controller='admin', action='view_datatypes_registry' )}" target="galaxy_main">View datatypes registry</a></div>
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='tool_versions' )}" target="galaxy_main">Tool versions</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='tool_versions' )}" target="galaxy_main">View tool lineage</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='memdump' )}" target="galaxy_main">Profile memory usage</a></div><div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='review_tool_migration_stages' )}" target="galaxy_main">Review tool migration stages</a></div>
%if installing_repository_ids:
<div class="toolTitle"><a href="${h.url_for( controller='admin_toolshed', action='monitor_repository_installation', tool_shed_repository_ids=installing_repository_ids )}" target="galaxy_main">Monitor installing tool shed repositories</a></div>
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
21 Sep '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/cd739bd3dca4/
changeset: cd739bd3dca4
user: jgoecks
date: 2012-09-21 17:14:56
summary: Place track filters in their own file.
affected #: 2 files
diff -r 040555fcc6b5341e2878c0d4ec33f54c712273c2 -r cd739bd3dca4859fecfe499fc976b0e0b6478238 static/scripts/viz/trackster/filters.js
--- /dev/null
+++ b/static/scripts/viz/trackster/filters.js
@@ -0,0 +1,623 @@
+define( ["libs/underscore"], function(_) {
+
+var extend = _.extend;
+
+/**
+ * Filters that enable users to show/hide data points dynamically.
+ */
+var Filter = function(obj_dict) {
+ this.manager = null;
+ this.name = obj_dict.name;
+ // Index into payload to filter.
+ this.index = obj_dict.index;
+ this.tool_id = obj_dict.tool_id;
+ // Name to use for filter when building expression for tool.
+ this.tool_exp_name = obj_dict.tool_exp_name;
+};
+
+extend(Filter.prototype, {
+ /**
+ * Convert filter to dictionary.
+ */
+ to_dict: function() {
+ return {
+ name: this.name,
+ index: this.index,
+ tool_id: this.tool_id,
+ tool_exp_name: this.tool_exp_name
+ };
+ }
+});
+
+/**
+ * Creates an action icon.
+ */
+var create_action_icon = function(title, css_class, on_click_fn) {
+ return $("<a/>").attr("href", "javascript:void(0);").attr("title", title)
+ .addClass("icon-button").addClass(css_class).tooltip()
+ .click(on_click_fn);
+};
+
+/**
+ * Number filters have a min, max as well as a low, high; low and high are used
+ */
+var NumberFilter = function(obj_dict) {
+ //
+ // Attribute init.
+ //
+ Filter.call(this, obj_dict);
+ // Filter low/high. These values are used to filter elements.
+ this.low = ('low' in obj_dict ? obj_dict.low : -Number.MAX_VALUE);
+ this.high = ('high' in obj_dict ? obj_dict.high : Number.MAX_VALUE);
+ // Slide min/max. These values are used to set/update slider.
+ this.min = ('min' in obj_dict ? obj_dict.min : Number.MAX_VALUE);
+ this.max = ('max' in obj_dict ? obj_dict.max : -Number.MAX_VALUE);
+ // UI elements associated with filter.
+ this.container = null;
+ this.slider = null;
+ this.slider_label = null;
+
+ //
+ // Create HTML.
+ //
+
+ // Function that supports inline text editing of slider values.
+ // Enable users to edit parameter's value via a text box.
+ var edit_slider_values = function(container, span, slider) {
+ container.click(function() {
+ var cur_value = span.text(),
+ max = parseFloat(slider.slider("option", "max")),
+ input_size = (max <= 1 ? 4 : max <= 1000000 ? max.toString().length : 6),
+ multi_value = false,
+ slider_row = $(this).parents(".slider-row");
+
+ // Row now has input.
+ slider_row.addClass("input");
+
+ // Increase input size if there are two values.
+ if (slider.slider("option", "values")) {
+ input_size = 2*input_size + 1;
+ multi_value = true;
+ }
+ span.text("");
+ // Temporary input for changing value.
+ $("<input type='text'/>").attr("size", input_size).attr("maxlength", input_size)
+ .attr("value", cur_value).appendTo(span).focus().select()
+ .click(function(e) {
+ // Don't want click to propogate up to values_span and restart everything.
+ e.stopPropagation();
+ }).blur(function() {
+ $(this).remove();
+ span.text(cur_value);
+ slider_row.removeClass("input");
+ }).keyup(function(e) {
+ if (e.keyCode === 27) {
+ // Escape key.
+ $(this).trigger("blur");
+ } else if (e.keyCode === 13) {
+ //
+ // Enter/return key initiates callback. If new value(s) are in slider range,
+ // change value (which calls slider's change() function).
+ //
+ var slider_min = slider.slider("option", "min"),
+ slider_max = slider.slider("option", "max"),
+ invalid = function(a_val) {
+ return (isNaN(a_val) || a_val > slider_max || a_val < slider_min);
+ },
+ new_value = $(this).val();
+ if (!multi_value) {
+ new_value = parseFloat(new_value);
+ if (invalid(new_value)) {
+ alert("Parameter value must be in the range [" + slider_min + "-" + slider_max + "]");
+ return $(this);
+ }
+ }
+ else { // Multi value.
+ new_value = new_value.split("-");
+ new_value = [parseFloat(new_value[0]), parseFloat(new_value[1])];
+ if (invalid(new_value[0]) || invalid(new_value[1])) {
+ alert("Parameter value must be in the range [" + slider_min + "-" + slider_max + "]");
+ return $(this);
+ }
+ }
+
+ // Updating the slider also updates slider values and removes input.
+ slider.slider((multi_value ? "values" : "value"), new_value);
+ slider_row.removeClass("input");
+ }
+ });
+ });
+ };
+
+ var filter = this;
+
+ filter.parent_div = $("<div/>").addClass("filter-row slider-row");
+
+ // Set up filter label (name, values).
+ var filter_label = $("<div/>").addClass("elt-label").appendTo(filter.parent_div),
+ name_span = $("<span/>").addClass("slider-name").text(filter.name + " ").appendTo(filter_label),
+ values_span = $("<span/>").text(this.low + "-" + this.high),
+ values_span_container = $("<span/>").addClass("slider-value").appendTo(filter_label).append("[").append(values_span).append("]");
+ filter.values_span = values_span;
+
+ // Set up slider for filter.
+ var slider_div = $("<div/>").addClass("slider").appendTo(filter.parent_div);
+ filter.control_element = $("<div/>").attr("id", filter.name + "-filter-control").appendTo(slider_div);
+ filter.control_element.slider({
+ range: true,
+ min: this.min,
+ max: this.max,
+ step: this.get_slider_step(this.min, this.max),
+ values: [this.low, this.high],
+ slide: function(event, ui) {
+ filter.slide(event, ui);
+ },
+ change: function(event, ui) {
+ filter.control_element.slider("option", "slide").call(filter.control_element, event, ui);
+ }
+ });
+ filter.slider = filter.control_element;
+ filter.slider_label = values_span;
+
+ // Enable users to edit slider values via text box.
+ edit_slider_values(values_span_container, values_span, filter.control_element);
+
+ // Set up filter display controls.
+ var display_controls_div = $("<div/>").addClass("display-controls").appendTo(filter.parent_div);
+ this.transparency_icon = create_action_icon("Use filter for data transparency", "layer-transparent",
+ function() {
+ if (filter.manager.alpha_filter !== filter) {
+ // Setting this filter as the alpha filter.
+ filter.manager.alpha_filter = filter;
+ // Update UI for new filter.
+ filter.manager.parent_div.find(".layer-transparent").removeClass("active").hide();
+ filter.transparency_icon.addClass("active").show();
+ }
+ else {
+ // Clearing filter as alpha filter.
+ filter.manager.alpha_filter = null;
+ filter.transparency_icon.removeClass("active");
+ }
+ filter.manager.track.request_draw(true, true);
+ } )
+ .appendTo(display_controls_div).hide();
+ this.height_icon = create_action_icon("Use filter for data height", "arrow-resize-090",
+ function() {
+ if (filter.manager.height_filter !== filter) {
+ // Setting this filter as the height filter.
+ filter.manager.height_filter = filter;
+ // Update UI for new filter.
+ filter.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();
+ filter.height_icon.addClass("active").show();
+ }
+ else {
+ // Clearing filter as alpha filter.
+ filter.manager.height_filter = null;
+ filter.height_icon.removeClass("active");
+ }
+ filter.manager.track.request_draw(true, true);
+ } )
+ .appendTo(display_controls_div).hide();
+ filter.parent_div.hover( function() {
+ filter.transparency_icon.show();
+ filter.height_icon.show();
+ },
+ function() {
+ if (filter.manager.alpha_filter !== filter) {
+ filter.transparency_icon.hide();
+ }
+ if (filter.manager.height_filter !== filter) {
+ filter.height_icon.hide();
+ }
+ } );
+
+ // Add to clear floating layout.
+ $("<div style='clear: both;'/>").appendTo(filter.parent_div);
+};
+extend(NumberFilter.prototype, {
+ /**
+ * Convert filter to dictionary.
+ */
+ to_dict: function() {
+ var obj_dict = Filter.prototype.to_dict.call(this);
+ return extend(obj_dict, {
+ type: 'number',
+ min: this.min,
+ max: this.max,
+ low: this.low,
+ high: this.high
+ });
+ },
+ /**
+ * Return a copy of filter.
+ */
+ copy: function() {
+ return new NumberFilter(
+ {
+ name: this.name,
+ index: this.index,
+ tool_id: this.tool_id,
+ tool_exp_name: this.tool_exp_name
+ });
+ },
+ /**
+ * Get step for slider.
+ */
+ // FIXME: make this a "static" function.
+ get_slider_step: function(min, max) {
+ var range = max - min;
+ return (range <= 2 ? 0.01 : 1);
+ },
+ /**
+ * Handle slide events.
+ */
+ slide: function(event, ui) {
+ var values = ui.values;
+
+ // Set new values in UI.
+ this.values_span.text(values[0] + "-" + values[1]);
+
+ // Set new values in filter.
+ this.low = values[0];
+ this.high = values[1];
+
+ // Set timeout to update if filter low, high are stable.
+ var self = this;
+ setTimeout(function() {
+ if (values[0] === self.low && values[1] === self.high) {
+ self.manager.track.request_draw(true, true);
+ }
+ }, 25);
+
+ },
+ /**
+ * Returns true if filter can be applied to element.
+ */
+ applies_to: function(element) {
+ if (element.length > this.index) {
+ return true;
+ }
+ return false;
+ },
+ /**
+ * Helper function: returns true if value in in filter's [low, high] range.
+ */
+ _keep_val: function(val) {
+ return (isNaN(val) || (val >= this.low && val <= this.high));
+ },
+ /**
+ * Returns true if (a) element's value(s) is in [low, high] (range is inclusive)
+ * or (b) if value is non-numeric and hence unfilterable.
+ */
+ keep: function(element) {
+ if ( !this.applies_to( element ) ) {
+ // No element to filter on.
+ return true;
+ }
+
+ // Keep value function.
+ var filter = this;
+
+ // Do filtering.
+ var to_filter = element[this.index];
+ if (to_filter instanceof Array) {
+ var returnVal = true;
+ for (var i = 0; i < to_filter.length; i++) {
+ if (!this._keep_val(to_filter[i])) {
+ // Exclude element.
+ returnVal = false;
+ break;
+ }
+ }
+ return returnVal;
+ }
+ else {
+ return this._keep_val(element[this.index]);
+ }
+ },
+ /**
+ * Update filter's min and max values based on element's values.
+ */
+ update_attrs: function(element) {
+ var updated = false;
+ if (!this.applies_to(element) ) {
+ return updated;
+ }
+
+ //
+ // Update filter's min, max based on element values.
+ //
+
+ // Make value(s) into an Array.
+ var values = element[this.index];
+ if (!(values instanceof Array)) {
+ values = [values];
+ }
+
+ // Loop through values and update min, max.
+ for (var i = 0; i < values.length; i++) {
+ var value = values[i];
+ if (value < this.min) {
+ this.min = Math.floor(value);
+ updated = true;
+ }
+ if (value > this.max) {
+ this.max = Math.ceil(value);
+ updated = true;
+ }
+ }
+ return updated;
+ },
+ /**
+ * Update filter's slider.
+ */
+ update_ui_elt: function () {
+ // Only show filter if min < max because filter is not useful otherwise. This
+ // covers all corner cases, such as when min, max have not been defined and
+ // when min == max.
+ if (this.min < this.max) {
+ this.parent_div.show();
+ }
+ else {
+ this.parent_div.hide();
+ }
+
+ var
+ slider_min = this.slider.slider("option", "min"),
+ slider_max = this.slider.slider("option", "max");
+ if (this.min < slider_min || this.max > slider_max) {
+ // Update slider min, max, step.
+ this.slider.slider("option", "min", this.min);
+ this.slider.slider("option", "max", this.max);
+ this.slider.slider("option", "step", this.get_slider_step(this.min, this.max));
+ // Refresh slider:
+ // TODO: do we want to keep current values or reset to min/max?
+ // Currently we reset values:
+ this.slider.slider("option", "values", [this.min, this.max]);
+ // To use the current values.
+ //var values = this.slider.slider( "option", "values" );
+ //this.slider.slider( "option", "values", values );
+ }
+ }
+});
+
+/**
+ * Manages a set of filters.
+ */
+var FiltersManager = function(track, obj_dict) {
+ this.track = track;
+ this.alpha_filter = null;
+ this.height_filter = null;
+ this.filters = [];
+
+ //
+ // Create HTML.
+ //
+
+ //
+ // Create parent div.
+ //
+ this.parent_div = $("<div/>").addClass("filters").hide();
+ // Disable dragging, double clicking, keys on div so that actions on slider do not impact viz.
+ this.parent_div.bind("drag", function(e) {
+ e.stopPropagation();
+ }).click(function(e) {
+ e.stopPropagation();
+ }).bind("dblclick", function(e) {
+ e.stopPropagation();
+ }).bind("keydown", function(e) {
+ e.stopPropagation();
+ });
+
+ //
+ // Restore state from dict.
+ //
+ if (obj_dict && 'filters' in obj_dict) { // Second condition needed for backward compatibility.
+ var
+ alpha_filter_name = ('alpha_filter' in obj_dict ? obj_dict.alpha_filter : null),
+ height_filter_name = ('height_filter' in obj_dict ? obj_dict.height_filter : null),
+ filters_dict = obj_dict.filters,
+ filter;
+ for (var i = 0; i < filters_dict.length; i++) {
+ if (filters_dict[i].type === 'number') {
+ filter = new NumberFilter(filters_dict[i]);
+ this.add_filter(filter);
+ if (filter.name === alpha_filter_name) {
+ this.alpha_filter = filter;
+ filter.transparency_icon.addClass("active").show();
+ }
+ if (filter.name === height_filter_name) {
+ this.height_filter = filter;
+ filter.height_icon.addClass("active").show();
+ }
+ }
+ else {
+ console.log("ERROR: unsupported filter: ", name, type);
+ }
+ }
+
+
+ if ('visible' in obj_dict && obj_dict.visible) {
+ this.parent_div.show();
+ }
+ }
+
+ // Add button to filter complete dataset.
+ if (this.filters.length !== 0) {
+ var run_buttons_row = $("<div/>").addClass("param-row").appendTo(this.parent_div);
+ var run_on_dataset_button = $("<input type='submit'/>").attr("value", "Run on complete dataset").appendTo(run_buttons_row);
+ var filter_manager = this;
+ run_on_dataset_button.click( function() {
+ filter_manager.run_on_dataset();
+ });
+ }
+
+};
+
+extend(FiltersManager.prototype, {
+ // HTML manipulation and inspection.
+ show: function() { this.parent_div.show(); },
+ hide: function() { this.parent_div.hide(); },
+ toggle: function() { this.parent_div.toggle(); },
+ visible: function() { return this.parent_div.is(":visible"); },
+ /**
+ * Returns dictionary for manager.
+ */
+ to_dict: function() {
+ var obj_dict = {},
+ filter_dicts = [],
+ filter;
+
+ // Include individual filter states.
+ for (var i = 0; i < this.filters.length; i++) {
+ filter = this.filters[i];
+ filter_dicts.push(filter.to_dict());
+ }
+ obj_dict.filters = filter_dicts;
+
+ // Include transparency, height filters.
+ obj_dict.alpha_filter = (this.alpha_filter ? this.alpha_filter.name : null);
+ obj_dict.height_filter = (this.height_filter ? this.height_filter.name : null);
+
+ // Include visibility.
+ obj_dict.visible = this.parent_div.is(":visible");
+
+ return obj_dict;
+ },
+ /**
+ * Return a copy of the manager.
+ */
+ copy: function(new_track) {
+ var copy = new FiltersManager(new_track);
+ for (var i = 0; i < this.filters.length; i++) {
+ copy.add_filter(this.filters[i].copy());
+ }
+ return copy;
+ },
+ /**
+ * Add a filter to the manager.
+ */
+ add_filter: function(filter) {
+ filter.manager = this;
+ this.parent_div.append(filter.parent_div);
+ this.filters.push(filter);
+ },
+ /**
+ * Remove all filters from manager.
+ */
+ remove_all: function() {
+ this.filters = [];
+ this.parent_div.children().remove();
+ },
+ /**
+ * Initialize filters.
+ */
+ init_filters: function() {
+ for (var i = 0; i < this.filters.length; i++) {
+ var filter = this.filters[i];
+ filter.update_ui_elt();
+ }
+ },
+ /**
+ * Clear filters so that they do not impact track display.
+ */
+ clear_filters: function() {
+ for (var i = 0; i < this.filters.length; i++) {
+ var filter = this.filters[i];
+ filter.slider.slider("option", "values", [filter.min, filter.max]);
+ }
+ this.alpha_filter = null;
+ this.height_filter = null;
+
+ // Hide icons for setting filters.
+ this.parent_div.find(".icon-button").hide();
+ },
+ run_on_dataset: function() {
+ // Get or create dictionary item.
+ var get_or_create_dict_item = function(dict, key, new_item) {
+ // Add new item to dict if
+ if (!(key in dict)) {
+ dict[key] = new_item;
+ }
+ return dict[key];
+ };
+
+ //
+ // Find and group active filters. Active filters are those being used to hide data.
+ // Filters with the same tool id are grouped.
+ //
+ var active_filters = {},
+ filter,
+ tool_filter_conditions;
+ for (var i = 0; i < this.filters.length; i++) {
+ filter = this.filters[i];
+ if (filter.tool_id) {
+ // Add filtering conditions if filter low/high are set.
+ if (filter.min !== filter.low) {
+ tool_filter_conditions = get_or_create_dict_item(active_filters, filter.tool_id, []);
+ tool_filter_conditions[tool_filter_conditions.length] = filter.tool_exp_name + " >= " + filter.low;
+ }
+ if (filter.max !== filter.high) {
+ tool_filter_conditions = get_or_create_dict_item(active_filters, filter.tool_id, []);
+ tool_filter_conditions[tool_filter_conditions.length] = filter.tool_exp_name + " <= " + filter.high;
+ }
+ }
+ }
+
+ //
+ // Use tools to run filters.
+ //
+
+ // Create list of (tool_id, tool_filters) tuples.
+ var active_filters_list = [];
+ for (var tool_id in active_filters) {
+ active_filters_list[active_filters_list.length] = [tool_id, active_filters[tool_id]];
+ }
+
+ // Invoke recursive function to run filters; this enables chaining of filters via
+ // iteratively application.
+ (function run_filter(input_dataset_id, filters) {
+ var
+ // Set up filtering info and params.
+ filter_tuple = filters[0],
+ tool_id = filter_tuple[0],
+ tool_filters = filter_tuple[1],
+ tool_filter_str = "(" + tool_filters.join(") and (") + ")",
+ url_params = {
+ cond: tool_filter_str,
+ input: input_dataset_id,
+ target_dataset_id: input_dataset_id,
+ tool_id: tool_id
+ };
+
+ // Remove current filter.
+ filters = filters.slice(1);
+
+ $.getJSON(run_tool_url, url_params, function(response) {
+ if (response.error) {
+ // General error.
+ show_modal("Filter Dataset",
+ "Error running tool " + tool_id,
+ { "Close" : hide_modal } );
+ }
+ else if (filters.length === 0) {
+ // No more filters to run.
+ show_modal("Filtering Dataset",
+ "Filter(s) are running on the complete dataset. Outputs are in dataset's history.",
+ { "Close" : hide_modal } );
+ }
+ else {
+ // More filters to run.
+ run_filter(response.dataset_id, filters);
+ }
+ });
+
+ })(this.track.dataset_id, active_filters_list);
+ }
+});
+
+return {
+ FiltersManager: FiltersManager
+};
+
+});
diff -r 040555fcc6b5341e2878c0d4ec33f54c712273c2 -r cd739bd3dca4859fecfe499fc976b0e0b6478238 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1,6 +1,7 @@
define( ["libs/underscore", "viz/visualization", "viz/trackster/util",
- "viz/trackster/slotting", "viz/trackster/painters", "mvc/data" ],
- function( _, visualization, util, slotting, painters, data ) {
+ "viz/trackster/slotting", "viz/trackster/painters", "mvc/data",
+ "viz/trackster/filters" ],
+ function( _, visualization, util, slotting, painters, data, filters ) {
var extend = _.extend;
var get_random_color = util.get_random_color;
@@ -586,7 +587,7 @@
moveable(this.container_div, this.drag_handle_class, ".group", this);
// Set up filters.
- this.filters_manager = new FiltersManager(this);
+ this.filters_manager = new filters.FiltersManager(this);
this.header_div.after(this.filters_manager.parent_div);
// For saving drawables' filter managers when group-level filtering is done:
this.saved_filters_managers = [];
@@ -600,7 +601,7 @@
if ('filters' in obj_dict) {
// FIXME: Pass collection_dict to DrawableCollection/Drawable will make this easier.
var old_manager = this.filters_manager;
- this.filters_manager = new FiltersManager(this, obj_dict.filters);
+ this.filters_manager = new filters.FiltersManager(this, obj_dict.filters);
old_manager.parent_div.replaceWith(this.filters_manager.parent_div);
if (obj_dict.filters.visible) {
@@ -1831,619 +1832,6 @@
});
/**
- * Filters that enable users to show/hide data points dynamically.
- */
-var Filter = function(obj_dict) {
- this.manager = null;
- this.name = obj_dict.name;
- // Index into payload to filter.
- this.index = obj_dict.index;
- this.tool_id = obj_dict.tool_id;
- // Name to use for filter when building expression for tool.
- this.tool_exp_name = obj_dict.tool_exp_name;
-};
-
-extend(Filter.prototype, {
- /**
- * Convert filter to dictionary.
- */
- to_dict: function() {
- return {
- name: this.name,
- index: this.index,
- tool_id: this.tool_id,
- tool_exp_name: this.tool_exp_name
- };
- }
-});
-
-/**
- * Creates an action icon.
- */
-var create_action_icon = function(title, css_class, on_click_fn) {
- return $("<a/>").attr("href", "javascript:void(0);").attr("title", title)
- .addClass("icon-button").addClass(css_class).tooltip()
- .click(on_click_fn);
-};
-
-/**
- * Number filters have a min, max as well as a low, high; low and high are used
- */
-var NumberFilter = function(obj_dict) {
- //
- // Attribute init.
- //
- Filter.call(this, obj_dict);
- // Filter low/high. These values are used to filter elements.
- this.low = ('low' in obj_dict ? obj_dict.low : -Number.MAX_VALUE);
- this.high = ('high' in obj_dict ? obj_dict.high : Number.MAX_VALUE);
- // Slide min/max. These values are used to set/update slider.
- this.min = ('min' in obj_dict ? obj_dict.min : Number.MAX_VALUE);
- this.max = ('max' in obj_dict ? obj_dict.max : -Number.MAX_VALUE);
- // UI elements associated with filter.
- this.container = null;
- this.slider = null;
- this.slider_label = null;
-
- //
- // Create HTML.
- //
-
- // Function that supports inline text editing of slider values.
- // Enable users to edit parameter's value via a text box.
- var edit_slider_values = function(container, span, slider) {
- container.click(function() {
- var cur_value = span.text(),
- max = parseFloat(slider.slider("option", "max")),
- input_size = (max <= 1 ? 4 : max <= 1000000 ? max.toString().length : 6),
- multi_value = false,
- slider_row = $(this).parents(".slider-row");
-
- // Row now has input.
- slider_row.addClass("input");
-
- // Increase input size if there are two values.
- if (slider.slider("option", "values")) {
- input_size = 2*input_size + 1;
- multi_value = true;
- }
- span.text("");
- // Temporary input for changing value.
- $("<input type='text'/>").attr("size", input_size).attr("maxlength", input_size)
- .attr("value", cur_value).appendTo(span).focus().select()
- .click(function(e) {
- // Don't want click to propogate up to values_span and restart everything.
- e.stopPropagation();
- }).blur(function() {
- $(this).remove();
- span.text(cur_value);
- slider_row.removeClass("input");
- }).keyup(function(e) {
- if (e.keyCode === 27) {
- // Escape key.
- $(this).trigger("blur");
- } else if (e.keyCode === 13) {
- //
- // Enter/return key initiates callback. If new value(s) are in slider range,
- // change value (which calls slider's change() function).
- //
- var slider_min = slider.slider("option", "min"),
- slider_max = slider.slider("option", "max"),
- invalid = function(a_val) {
- return (isNaN(a_val) || a_val > slider_max || a_val < slider_min);
- },
- new_value = $(this).val();
- if (!multi_value) {
- new_value = parseFloat(new_value);
- if (invalid(new_value)) {
- alert("Parameter value must be in the range [" + slider_min + "-" + slider_max + "]");
- return $(this);
- }
- }
- else { // Multi value.
- new_value = new_value.split("-");
- new_value = [parseFloat(new_value[0]), parseFloat(new_value[1])];
- if (invalid(new_value[0]) || invalid(new_value[1])) {
- alert("Parameter value must be in the range [" + slider_min + "-" + slider_max + "]");
- return $(this);
- }
- }
-
- // Updating the slider also updates slider values and removes input.
- slider.slider((multi_value ? "values" : "value"), new_value);
- slider_row.removeClass("input");
- }
- });
- });
- };
-
- var filter = this;
-
- filter.parent_div = $("<div/>").addClass("filter-row slider-row");
-
- // Set up filter label (name, values).
- var filter_label = $("<div/>").addClass("elt-label").appendTo(filter.parent_div),
- name_span = $("<span/>").addClass("slider-name").text(filter.name + " ").appendTo(filter_label),
- values_span = $("<span/>").text(this.low + "-" + this.high),
- values_span_container = $("<span/>").addClass("slider-value").appendTo(filter_label).append("[").append(values_span).append("]");
- filter.values_span = values_span;
-
- // Set up slider for filter.
- var slider_div = $("<div/>").addClass("slider").appendTo(filter.parent_div);
- filter.control_element = $("<div/>").attr("id", filter.name + "-filter-control").appendTo(slider_div);
- filter.control_element.slider({
- range: true,
- min: this.min,
- max: this.max,
- step: this.get_slider_step(this.min, this.max),
- values: [this.low, this.high],
- slide: function(event, ui) {
- filter.slide(event, ui);
- },
- change: function(event, ui) {
- filter.control_element.slider("option", "slide").call(filter.control_element, event, ui);
- }
- });
- filter.slider = filter.control_element;
- filter.slider_label = values_span;
-
- // Enable users to edit slider values via text box.
- edit_slider_values(values_span_container, values_span, filter.control_element);
-
- // Set up filter display controls.
- var display_controls_div = $("<div/>").addClass("display-controls").appendTo(filter.parent_div);
- this.transparency_icon = create_action_icon("Use filter for data transparency", "layer-transparent",
- function() {
- if (filter.manager.alpha_filter !== filter) {
- // Setting this filter as the alpha filter.
- filter.manager.alpha_filter = filter;
- // Update UI for new filter.
- filter.manager.parent_div.find(".layer-transparent").removeClass("active").hide();
- filter.transparency_icon.addClass("active").show();
- }
- else {
- // Clearing filter as alpha filter.
- filter.manager.alpha_filter = null;
- filter.transparency_icon.removeClass("active");
- }
- filter.manager.track.request_draw(true, true);
- } )
- .appendTo(display_controls_div).hide();
- this.height_icon = create_action_icon("Use filter for data height", "arrow-resize-090",
- function() {
- if (filter.manager.height_filter !== filter) {
- // Setting this filter as the height filter.
- filter.manager.height_filter = filter;
- // Update UI for new filter.
- filter.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();
- filter.height_icon.addClass("active").show();
- }
- else {
- // Clearing filter as alpha filter.
- filter.manager.height_filter = null;
- filter.height_icon.removeClass("active");
- }
- filter.manager.track.request_draw(true, true);
- } )
- .appendTo(display_controls_div).hide();
- filter.parent_div.hover( function() {
- filter.transparency_icon.show();
- filter.height_icon.show();
- },
- function() {
- if (filter.manager.alpha_filter !== filter) {
- filter.transparency_icon.hide();
- }
- if (filter.manager.height_filter !== filter) {
- filter.height_icon.hide();
- }
- } );
-
- // Add to clear floating layout.
- $("<div style='clear: both;'/>").appendTo(filter.parent_div);
-};
-extend(NumberFilter.prototype, {
- /**
- * Convert filter to dictionary.
- */
- to_dict: function() {
- var obj_dict = Filter.prototype.to_dict.call(this);
- return extend(obj_dict, {
- type: 'number',
- min: this.min,
- max: this.max,
- low: this.low,
- high: this.high
- });
- },
- /**
- * Return a copy of filter.
- */
- copy: function() {
- return new NumberFilter(
- {
- name: this.name,
- index: this.index,
- tool_id: this.tool_id,
- tool_exp_name: this.tool_exp_name
- });
- },
- /**
- * Get step for slider.
- */
- // FIXME: make this a "static" function.
- get_slider_step: function(min, max) {
- var range = max - min;
- return (range <= 2 ? 0.01 : 1);
- },
- /**
- * Handle slide events.
- */
- slide: function(event, ui) {
- var values = ui.values;
-
- // Set new values in UI.
- this.values_span.text(values[0] + "-" + values[1]);
-
- // Set new values in filter.
- this.low = values[0];
- this.high = values[1];
-
- // Set timeout to update if filter low, high are stable.
- var self = this;
- setTimeout(function() {
- if (values[0] === self.low && values[1] === self.high) {
- self.manager.track.request_draw(true, true);
- }
- }, 25);
-
- },
- /**
- * Returns true if filter can be applied to element.
- */
- applies_to: function(element) {
- if (element.length > this.index) {
- return true;
- }
- return false;
- },
- /**
- * Helper function: returns true if value in in filter's [low, high] range.
- */
- _keep_val: function(val) {
- return (isNaN(val) || (val >= this.low && val <= this.high));
- },
- /**
- * Returns true if (a) element's value(s) is in [low, high] (range is inclusive)
- * or (b) if value is non-numeric and hence unfilterable.
- */
- keep: function(element) {
- if ( !this.applies_to( element ) ) {
- // No element to filter on.
- return true;
- }
-
- // Keep value function.
- var filter = this;
-
- // Do filtering.
- var to_filter = element[this.index];
- if (to_filter instanceof Array) {
- var returnVal = true;
- for (var i = 0; i < to_filter.length; i++) {
- if (!this._keep_val(to_filter[i])) {
- // Exclude element.
- returnVal = false;
- break;
- }
- }
- return returnVal;
- }
- else {
- return this._keep_val(element[this.index]);
- }
- },
- /**
- * Update filter's min and max values based on element's values.
- */
- update_attrs: function(element) {
- var updated = false;
- if (!this.applies_to(element) ) {
- return updated;
- }
-
- //
- // Update filter's min, max based on element values.
- //
-
- // Make value(s) into an Array.
- var values = element[this.index];
- if (!(values instanceof Array)) {
- values = [values];
- }
-
- // Loop through values and update min, max.
- for (var i = 0; i < values.length; i++) {
- var value = values[i];
- if (value < this.min) {
- this.min = Math.floor(value);
- updated = true;
- }
- if (value > this.max) {
- this.max = Math.ceil(value);
- updated = true;
- }
- }
- return updated;
- },
- /**
- * Update filter's slider.
- */
- update_ui_elt: function () {
- // Only show filter if min < max because filter is not useful otherwise. This
- // covers all corner cases, such as when min, max have not been defined and
- // when min == max.
- if (this.min < this.max) {
- this.parent_div.show();
- }
- else {
- this.parent_div.hide();
- }
-
- var
- slider_min = this.slider.slider("option", "min"),
- slider_max = this.slider.slider("option", "max");
- if (this.min < slider_min || this.max > slider_max) {
- // Update slider min, max, step.
- this.slider.slider("option", "min", this.min);
- this.slider.slider("option", "max", this.max);
- this.slider.slider("option", "step", this.get_slider_step(this.min, this.max));
- // Refresh slider:
- // TODO: do we want to keep current values or reset to min/max?
- // Currently we reset values:
- this.slider.slider("option", "values", [this.min, this.max]);
- // To use the current values.
- //var values = this.slider.slider( "option", "values" );
- //this.slider.slider( "option", "values", values );
- }
- }
-});
-
-/**
- * Manages a set of filters.
- */
-var FiltersManager = function(track, obj_dict) {
- this.track = track;
- this.alpha_filter = null;
- this.height_filter = null;
- this.filters = [];
-
- //
- // Create HTML.
- //
-
- //
- // Create parent div.
- //
- this.parent_div = $("<div/>").addClass("filters").hide();
- // Disable dragging, double clicking, keys on div so that actions on slider do not impact viz.
- this.parent_div.bind("drag", function(e) {
- e.stopPropagation();
- }).click(function(e) {
- e.stopPropagation();
- }).bind("dblclick", function(e) {
- e.stopPropagation();
- }).bind("keydown", function(e) {
- e.stopPropagation();
- });
-
- //
- // Restore state from dict.
- //
- if (obj_dict && 'filters' in obj_dict) { // Second condition needed for backward compatibility.
- var
- alpha_filter_name = ('alpha_filter' in obj_dict ? obj_dict.alpha_filter : null),
- height_filter_name = ('height_filter' in obj_dict ? obj_dict.height_filter : null),
- filters_dict = obj_dict.filters,
- filter;
- for (var i = 0; i < filters_dict.length; i++) {
- if (filters_dict[i].type === 'number') {
- filter = new NumberFilter(filters_dict[i]);
- this.add_filter(filter);
- if (filter.name === alpha_filter_name) {
- this.alpha_filter = filter;
- filter.transparency_icon.addClass("active").show();
- }
- if (filter.name === height_filter_name) {
- this.height_filter = filter;
- filter.height_icon.addClass("active").show();
- }
- }
- else {
- console.log("ERROR: unsupported filter: ", name, type);
- }
- }
-
-
- if ('visible' in obj_dict && obj_dict.visible) {
- this.parent_div.show();
- }
- }
-
- // Add button to filter complete dataset.
- if (this.filters.length !== 0) {
- var run_buttons_row = $("<div/>").addClass("param-row").appendTo(this.parent_div);
- var run_on_dataset_button = $("<input type='submit'/>").attr("value", "Run on complete dataset").appendTo(run_buttons_row);
- var filter_manager = this;
- run_on_dataset_button.click( function() {
- filter_manager.run_on_dataset();
- });
- }
-
-};
-
-extend(FiltersManager.prototype, {
- // HTML manipulation and inspection.
- show: function() { this.parent_div.show(); },
- hide: function() { this.parent_div.hide(); },
- toggle: function() { this.parent_div.toggle(); },
- visible: function() { return this.parent_div.is(":visible"); },
- /**
- * Returns dictionary for manager.
- */
- to_dict: function() {
- var obj_dict = {},
- filter_dicts = [],
- filter;
-
- // Include individual filter states.
- for (var i = 0; i < this.filters.length; i++) {
- filter = this.filters[i];
- filter_dicts.push(filter.to_dict());
- }
- obj_dict.filters = filter_dicts;
-
- // Include transparency, height filters.
- obj_dict.alpha_filter = (this.alpha_filter ? this.alpha_filter.name : null);
- obj_dict.height_filter = (this.height_filter ? this.height_filter.name : null);
-
- // Include visibility.
- obj_dict.visible = this.parent_div.is(":visible");
-
- return obj_dict;
- },
- /**
- * Return a copy of the manager.
- */
- copy: function(new_track) {
- var copy = new FiltersManager(new_track);
- for (var i = 0; i < this.filters.length; i++) {
- copy.add_filter(this.filters[i].copy());
- }
- return copy;
- },
- /**
- * Add a filter to the manager.
- */
- add_filter: function(filter) {
- filter.manager = this;
- this.parent_div.append(filter.parent_div);
- this.filters.push(filter);
- },
- /**
- * Remove all filters from manager.
- */
- remove_all: function() {
- this.filters = [];
- this.parent_div.children().remove();
- },
- /**
- * Initialize filters.
- */
- init_filters: function() {
- for (var i = 0; i < this.filters.length; i++) {
- var filter = this.filters[i];
- filter.update_ui_elt();
- }
- },
- /**
- * Clear filters so that they do not impact track display.
- */
- clear_filters: function() {
- for (var i = 0; i < this.filters.length; i++) {
- var filter = this.filters[i];
- filter.slider.slider("option", "values", [filter.min, filter.max]);
- }
- this.alpha_filter = null;
- this.height_filter = null;
-
- // Hide icons for setting filters.
- this.parent_div.find(".icon-button").hide();
- },
- run_on_dataset: function() {
- // Get or create dictionary item.
- var get_or_create_dict_item = function(dict, key, new_item) {
- // Add new item to dict if
- if (!(key in dict)) {
- dict[key] = new_item;
- }
- return dict[key];
- };
-
- //
- // Find and group active filters. Active filters are those being used to hide data.
- // Filters with the same tool id are grouped.
- //
- var active_filters = {},
- filter,
- tool_filter_conditions;
- for (var i = 0; i < this.filters.length; i++) {
- filter = this.filters[i];
- if (filter.tool_id) {
- // Add filtering conditions if filter low/high are set.
- if (filter.min !== filter.low) {
- tool_filter_conditions = get_or_create_dict_item(active_filters, filter.tool_id, []);
- tool_filter_conditions[tool_filter_conditions.length] = filter.tool_exp_name + " >= " + filter.low;
- }
- if (filter.max !== filter.high) {
- tool_filter_conditions = get_or_create_dict_item(active_filters, filter.tool_id, []);
- tool_filter_conditions[tool_filter_conditions.length] = filter.tool_exp_name + " <= " + filter.high;
- }
- }
- }
-
- //
- // Use tools to run filters.
- //
-
- // Create list of (tool_id, tool_filters) tuples.
- var active_filters_list = [];
- for (var tool_id in active_filters) {
- active_filters_list[active_filters_list.length] = [tool_id, active_filters[tool_id]];
- }
-
- // Invoke recursive function to run filters; this enables chaining of filters via
- // iteratively application.
- (function run_filter(input_dataset_id, filters) {
- var
- // Set up filtering info and params.
- filter_tuple = filters[0],
- tool_id = filter_tuple[0],
- tool_filters = filter_tuple[1],
- tool_filter_str = "(" + tool_filters.join(") and (") + ")",
- url_params = {
- cond: tool_filter_str,
- input: input_dataset_id,
- target_dataset_id: input_dataset_id,
- tool_id: tool_id
- },
- // Remove current filter.
- filters = filters.slice(1);
-
- $.getJSON(run_tool_url, url_params, function(response) {
- if (response.error) {
- // General error.
- show_modal("Filter Dataset",
- "Error running tool " + tool_id,
- { "Close" : hide_modal } );
- }
- else if (filters.length === 0) {
- // No more filters to run.
- show_modal("Filtering Dataset",
- "Filter(s) are running on the complete dataset. Outputs are in dataset's history.",
- { "Close" : hide_modal } );
- }
- else {
- // More filters to run.
- run_filter(response.dataset_id, filters);
- }
- });
-
- })(this.track.dataset_id, active_filters_list);
- }
-});
-
-/**
* Generates scale values based on filter and feature's value for filter.
*/
var FilterScaler = function(filter, default_val) {
@@ -3224,7 +2612,7 @@
moveable(track.container_div, track.drag_handle_class, ".group", track);
// Attribute init.
- this.filters_manager = new FiltersManager(this, ('filters' in obj_dict ? obj_dict.filters : null));
+ this.filters_manager = new filters.FiltersManager(this, ('filters' in obj_dict ? obj_dict.filters : null));
// HACK: set filters manager for data manager.
// FIXME: prolly need function to set filters and update data_manager reference.
this.data_manager.set('filters_manager', this.filters_manager);
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0