diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py
index 9e6a99704af..3169afe09a4 100644
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -1,6 +1,9 @@
from galaxy.util.bunch import Bunch
from galaxy.tools.parameters import *
+import logging
+log = logging.getLogger( __name__ )
+
class ToolAction( object ):
"""
The actions to be taken when a tool is run (after parameters have
@@ -10,9 +13,7 @@ class ToolAction( object ):
raise TypeError("Abstract method")
class DefaultToolAction( object ):
- """
- Default tool action is to run an external command
- """
+ """Default tool action is to run an external command"""
def collect_input_datasets( self, tool, param_values ):
"""
@@ -102,16 +103,11 @@ class DefaultToolAction( object ):
# the type should match the input
if ext == "input":
ext = input_ext
- # FIXME: What does this flush?
- trans.app.model.flush()
data = trans.app.model.Dataset(extension=ext)
- # Commit the dataset immediately so it gets database assigned
- # unique id
+ # Commit the dataset immediately so it gets database assigned unique id
data.flush()
# Create an empty file immediately
open( data.file_name, "w" ).close()
- # FIXME: What does this flush?
- trans.app.model.flush()
# This may not be neccesary with the new parent/child associations
data.designation = name
# Set the extension / datatype
diff --git a/lib/galaxy/tools/dynamic_options.py b/lib/galaxy/tools/dynamic_options.py
new file mode 100644
index 00000000000..d8d31b9c0db
--- /dev/null
+++ b/lib/galaxy/tools/dynamic_options.py
@@ -0,0 +1,155 @@
+
+import sys, os, logging
+
+log = logging.getLogger(__name__)
+
+class DynamicOptions( object ):
+ """Handles dynamically generated SelectToolParameter options"""
+ def __init__( self, elem ):
+ self.data_ref = elem.get( 'data_ref', None)
+ self.from_file = elem.get( 'from_file', None )
+ assert self.from_file is not None, "Value for option data file not found"
+ self.func = elem.get( 'func', None )
+ assert self.func is not None, "Value for option generator function not found"
+ self.func_params = elem.findall( 'func_param' )
+ def get_dataset( self, trans, other_values ):
+ # No value indicates a configuration error, the named DataToolParameter must preceed this parameter in the tool config
+ assert self.data_ref in other_values, "Value for associated DataToolParameter not found"
+ # Get the value of the associated DataToolParameter (a dataset)
+ dataset = other_values[ self.data_ref ]
+ if dataset is None or dataset == '':
+ """
+ Both of these values indicate that no dataset is selected. However, 'None' indicates that the dataset is optional
+ while '' indicates that it is not. Currently column parameters do not work well with optional datasets.
+ """
+ return None
+ # TODO: this can be eliminated after Dan's script is run.
+ dataset.set_meta()
+ return dataset
+ #TODO: the following functions should be generalized so that they are not specific to
+ #certain tools (e.g., encode). We may need to standardize data file formats to be able to do this.
+ def load_from_file_for_build( self ):
+ dict = {}
+ for line in open( self.from_file ):
+ if line and not line.startswith( '#' ):
+ try:
+ fields = line.rstrip('\r\n').split( "\t" )
+ if not fields[0] in dict:
+ dict[ fields[0] ] = []
+ dict[ fields[0] ].append( (fields[1], fields[2]) )
+ except:
+ continue
+ return dict
+ def get_options_for_build( self, trans, other_values ):
+ legal_values = set()
+ options = []
+ dataset = self.get_dataset( trans, other_values )
+ if dataset is None:
+ return legal_values, options
+ dict = self.load_from_file_for_build()
+ if dataset.dbkey in dict:
+ for (descript, scorefile) in dict[ dataset.dbkey ]:
+ options.append( (descript, scorefile, False) )
+ legal_values.add( scorefile )
+ return legal_values, options
+ def load_from_file_for_encode( self ):
+ encode_sets= {}
+ legal_values = set()
+ try:
+ for line in open( self.from_file ):
+ if line and not line.startswith( '#' ):
+ try:
+ fields = line.rstrip('\r\n').split( "\t" )
+ encode_group = fields[0]
+ build = fields[1]
+ description = fields[2]
+ uid = fields[3]
+ path = fields[4]
+ try: file_type = fields[5]
+ except: file_type = "bed"
+ #TODO: will remove this later, when galaxy can handle gff files
+ if file_type != "bed": continue
+ #verify that file exists before making it an option
+ if not os.path.isfile(path):
+ continue
+ except:
+ continue
+ #check if group is initialized, if not inititalize
+ try: temp = encode_sets[encode_group]
+ except: encode_sets[encode_group] = {}
+ #add data to group in proper build
+ try:
+ encode_sets[encode_group][build].append((description, uid, False))
+ legal_values.add( uid )
+ except:
+ encode_sets[encode_group][build]=[]
+ encode_sets[encode_group][build].append((description, uid, False))
+ legal_values.add( uid )
+ #Order by description and date, highest date on top and bold
+ for group in encode_sets:
+ for build in encode_sets[ group ]:
+ ordered_build = []
+ for description, uid, selected in encode_sets[ group ][ build ]:
+ item = {}
+ item['date']=0
+ item['description'] = ""
+ item['uid']=uid
+ item['selected']=selected
+ item['partitioned']=False
+
+ if description[-21:]=='[gencode_partitioned]':
+ item['date'] = description[-31:-23]
+ item['description'] = description[0:-32]
+ item['partitioned']=True
+ else:
+ item['date'] = description[-9:-1]
+ item['description'] = description[0:-10]
+
+ for i in range(len(ordered_build)):
+ ordered_description, ordered_uid, ordered_selected, ordered_item = ordered_build[i]
+ if item['description'] < ordered_item['description']:
+ ordered_build.insert(i, (description, uid, selected, item) )
+ break
+ if item['description'] == ordered_item['description'] and item['partitioned'] == ordered_item['partitioned']:
+ if int(item['date']) > int(ordered_item['date']):
+ ordered_build.insert(i, (description, uid, selected, item) )
+ break
+ else:
+ ordered_build.append( (description, uid, selected, item) )
+
+ last_desc = None
+ last_partitioned = None
+ for i in range(len(ordered_build)) :
+ description, uid, selected, item = ordered_build[i]
+ if item['partitioned'] != last_partitioned or last_desc != item['description']:
+ last_desc = item['description']
+ description = ""+description+""
+ else:
+ last_desc = item['description']
+ last_partitioned = item['partitioned']
+ encode_sets[group][build][i] = (description, uid, selected)
+ except Exception, exc:
+ #TODO: Fix this...
+ print >>sys.stdout, 'load_from_file_for_encode: initialization error -> %s' % exc
+ return legal_values, encode_sets
+ #return available datasets for group and build, set None option as selected for hg16
+ def get_options_for_encode( self, trans, other_values ):
+ assert len( self.func_params ) == 2, "Values for 'build' and 'encode group' not found"
+ for func_param in self.func_params:
+ if func_param.get( 'name' ).strip() == 'build':
+ build = func_param.get( 'value' ).strip()
+ elif func_param.get( 'name' ).strip() == 'encode_group':
+ encode_group = func_param.get( 'value' ).strip()
+ legal_values = set()
+ options = []
+ legal_values, dict = self.load_from_file_for_encode()
+ if len( dict ) < 1:
+ options.append(('No data available for this build','None',True))
+ legal_values.add( 'None' )
+ else:
+ try:
+ options = dict[encode_group][build][0:]
+ except:
+ options.append(('No data available for this build','None',True))
+ legal_values.add( 'None' )
+ return legal_values, options
diff --git a/lib/galaxy/tools/parameters.py b/lib/galaxy/tools/parameters.py
index cd8d776e887..829ab97771b 100644
--- a/lib/galaxy/tools/parameters.py
+++ b/lib/galaxy/tools/parameters.py
@@ -5,7 +5,7 @@ Classes encapsulating tool parameters
import logging, string, sys
from galaxy import config, datatypes, util
from galaxy.datatypes.tabular import *
-import validation
+import validation, dynamic_options
from elementtree.ElementTree import XML, Element
# For BaseURLToolParameter
@@ -298,14 +298,7 @@ class HiddenToolParameter( ToolParameter ):
ToolParameter.__init__( self, tool, elem )
self.name = elem.get( 'name' )
self.value = elem.get( 'value' )
- self.dynamic_options = elem.get( "dynamic_options", None )
def get_html_field( self, trans=None, value=None, other_values={} ):
- if self.dynamic_options:
- # Add GALAXY_TOOL_PARAMS to locals for backward compatibility
- locals = dict( other_values )
- locals['GALAXY_TOOL_PARAMS'] = other_values
- options = eval( self.dynamic_options, self.tool.code_namespace, locals )
- self.value = options
return form_builder.HiddenField( self.name, self.value )
def get_initial_value( self, trans, context ):
return self.value
@@ -424,13 +417,26 @@ class SelectToolParameter( ToolParameter ):
self.legal_values.add( value )
selected = ( option.get( "selected", None ) == "true" )
self.options.append( ( option.text, value, selected ) )
+ select_options = elem.find( 'select_options' )
+ if select_options is not None:
+ self.select_options = dynamic_options.DynamicOptions( select_options )
+ else:
+ self.select_options = None
def get_options( self, trans, other_values ):
- if self.dynamic_options:
+ if self.select_options:
+ func = '''self.select_options.%s( trans, other_values )''' %self.select_options.func
+ legal_values, options = eval( func )
+ for value in legal_values:
+ self.legal_values.add( value )
+ return options
+ elif self.dynamic_options:
return eval( self.dynamic_options, self.tool.code_namespace, other_values )
else:
return self.options
def get_legal_values( self, trans, other_values ):
- if self.dynamic_options:
+ if self.select_options:
+ return self.legal_values
+ elif self.dynamic_options:
return set( v for _, v, _ in eval( self.dynamic_options, self.tool.code_namespace, other_values ) )
else:
return self.legal_values
@@ -480,6 +486,11 @@ class SelectToolParameter( ToolParameter ):
elif len( value ) == 1:
value = value[0]
return value
+ def get_dependencies( self ):
+ try:
+ if self.select_options.data_ref is None: return []
+ else: return [ self.select_options.data_ref ]
+ except: return []
class GenomeBuildParameter( SelectToolParameter ):
"""
@@ -545,7 +556,7 @@ class ColumnListParameter( SelectToolParameter ):
>>> dtp = DataToolParameter( None, XML( '' ) )
>>> print dtp.name
blah
- >>> clp = ColumnListParameter ( None, XML( '' ) )
+ >>> clp = ColumnListParameter ( None, XML( '' ) )
>>> print clp.name
numerical_column
"""
@@ -553,9 +564,8 @@ class ColumnListParameter( SelectToolParameter ):
SelectToolParameter.__init__( self, tool, elem )
self.tool = tool
self.numerical = str_bool( elem.get( "numerical", False ))
+ self.force_select = str_bool( elem.get( "force_select", True ))
self.data_ref = elem.get( "data_ref", None )
- if self.data_ref is None:
- self.data_ref = elem.get( "assoc_dataset", None )
def get_column_list( self, trans, other_values ):
"""
Generate a select list containing the columns of the associated
@@ -577,6 +587,8 @@ class ColumnListParameter( SelectToolParameter ):
# Just to be safe... (FIXME: Is this still neccesary?)
dataset.set_meta()
# Generate options
+ if not dataset.metadata.columns:
+ return column_list
if self.numerical:
# If numerical was requsted, filter columns based on metadata
for i, col in enumerate( dataset.metadata.column_types ):
@@ -587,9 +599,17 @@ class ColumnListParameter( SelectToolParameter ):
return column_list
def get_options( self, trans, other_values ):
column_list = self.get_column_list( trans, other_values )
- return [ ( "c" + col, col, False ) for col in column_list ]
+ options = []
+ if len( column_list ) > 0 and not self.force_select:
+ options.append( ('?', 'None', False) )
+ for col in column_list:
+ options.append( ( "c" + col, col, False ) )
+ return options
def get_legal_values( self, trans, other_values ):
- return set( self.get_column_list( trans, other_values ) )
+ legal_values = set( self.get_column_list( trans, other_values ) )
+ if not self.force_select:
+ legal_values.add( 'None' )
+ return legal_values
def get_dependencies( self ):
return [ self.data_ref ]
@@ -636,8 +656,6 @@ class DataToolParameter( ToolParameter ):
self.formats = tuple( formats )
self.multiple = str_bool( elem.get( 'multiple', False ) )
self.optional = str_bool( elem.get( 'optional', False ) )
- self.refresh_on_change = str_bool( elem.get( "refresh_on_change", False ))
- self.dynamic_options = elem.get( "dynamic_options", None )
def get_html_field( self, trans=None, value=None, other_values={} ):
assert trans is not None, "DataToolParameter requires a trans"
@@ -646,10 +664,6 @@ class DataToolParameter( ToolParameter ):
if value is not None:
if type( value ) != list: value = [ value ]
field = form_builder.SelectField( self.name, self.multiple, None, self.refresh_on_change )
- if self.dynamic_options:
- # Dynamic options for a DataToolParameter specify limits on acceptrable build, id, or extension
- option_build, option_id, option_extension = \
- eval( self.dynamic_options, self.tool.code_namespace, other_values )
# CRUCIAL: the dataset_collector function needs to be local to DataToolParameter.get_html_field()
def dataset_collector( datasets, parent_hid ):
for i, data in enumerate( datasets ):
@@ -657,18 +671,9 @@ class DataToolParameter( ToolParameter ):
hid = "%s.%d" % ( parent_hid, i + 1 )
else:
hid = str( data.hid )
- if self.dynamic_options:
- if ( isinstance( data.datatype, self.formats )
- and (data.dbkey == option_build) and (data.id != option_id)
- and (data.extension in option_extension)
- and not data.deleted
- and data.state not in [data.states.FAKE, data.states.ERROR] ):
- selected = ( value and ( data in value ) )
- field.add_option( "%s: %s" % ( hid, data.name[:30] ), data.id, selected )
- else:
- if isinstance( data.datatype, self.formats) and not data.deleted and data.state not in [data.states.FAKE, data.states.ERROR]:
- selected = ( value and ( data in value ) )
- field.add_option( "%s: %s" % ( hid, data.name[:30] ), data.id, selected )
+ if isinstance( data.datatype, self.formats) and not data.deleted and data.state not in [data.states.FAKE, data.states.ERROR]:
+ selected = ( value and ( data in value ) )
+ field.add_option( "%s: %s" % ( hid, data.name[:30] ), data.id, selected )
# Also collect children via association object
dataset_collector( [ assoc.child for assoc in data.children ], hid )
dataset_collector( history.datasets, None )
@@ -695,22 +700,11 @@ class DataToolParameter( ToolParameter ):
if trans is None or trans.history is None:
return None
history = trans.history
- if self.dynamic_options:
- # Dynamic options for a DataToolParameter specify limits on acceptrable build, id, or extension
- option_build, option_id, option_extension = \
- eval( self.dynamic_options, self.tool.code_namespace, other_values )
most_recent_dataset = [None]
def dataset_collector( datasets ):
for i, data in enumerate( datasets ):
- if self.dynamic_options:
- if ( isinstance( data.datatype, self.formats )
- and (data.dbkey == option_build) and (data.id != option_id)
- and (data.extension in option_extension)
- and not data.deleted ):
- most_recent_dataset[0] = data
- else:
- if isinstance( data.datatype, self.formats) and not data.deleted:
- most_recent_dataset[0] = data
+ if isinstance( data.datatype, self.formats) and not data.deleted and data.state not in [data.states.FAKE, data.states.ERROR]:
+ most_recent_dataset[0] = data
# Also collect children via association object
dataset_collector( [ assoc.child for assoc in data.children ] )
dataset_collector( history.datasets )
@@ -813,7 +807,6 @@ parameter_types = dict( text = TextToolParameter,
boolean = BooleanToolParameter,
genomebuild = GenomeBuildParameter,
select = SelectToolParameter,
- columnlist = ColumnListParameter,
data_column = ColumnListParameter,
hidden = HiddenToolParameter,
baseurl = BaseURLToolParameter,
diff --git a/tools/data_source/encode_import_all_latest_datasets.xml b/tools/data_source/encode_import_all_latest_datasets.xml
index df7b643ddf0..76d2772268e 100644
--- a/tools/data_source/encode_import_all_latest_datasets.xml
+++ b/tools/data_source/encode_import_all_latest_datasets.xml
@@ -2,11 +2,21 @@
-
+
-