For Power-Users‎ > ‎

5. Adding parameters to your tools

In the following steps will be show how to add new parameter types to a Galaxy tool definition as, for example, a date and a date span picker.
The idea is to add a parameter as
<param format="YYYYMMDD" name="input2" type="date" label="Select a date"/>
where format specify the date format (in this example a valid date il 20120105)

Create your datetime.py parameter definition file in galaxy-es/lib/galaxy/tools/parameters

"""
Date tool parameters.
"""
from cgi import escape
import operator, sys, os, logging
from basic import *
import galaxy.tools
import logging, string, sys, os, os.path
from elementtree.ElementTree import XML, Element
from galaxy import config, datatypes, util
from galaxy.util.bunch import Bunch
from galaxy.util import string_as_bool, sanitize_param
# For BaseURLToolParameter
from galaxy.web import url_for
import galaxy.model

Define the parameter tool class

class DateTimeToolParameter( ToolParameter):
   def __init__( self, tool, elem ):
       ToolParameter.__init__( self, tool, elem )

  self.value = elem.get('value',"")

       self.value = elem.get('format',"YYYYMMDD")

   def get_html_field( self, trans=None, value=None, other_values={} ):
       if value is None: value = self.value

       return DateField( self.name, value)

   def get_initial_value( self, trans, context ):

       return self.value

The DateTimeToolParameter class provides the general parameter behaviour, but a lower level class is needed in order to perform the HTML rendering: the DateTimeField.
Add the DateTimeField class (and its parent BaseField class) to the same datetime.py file:

class BaseField(object):
   def get_html( self, prefix="" ):
       """Returns the html widget corresponding to the parameter"""
       raise TypeError( "Abstract Method" )
   def get_disabled_str( self, disabled=False ):
       if disabled:
           return ' disabled="disabled"'
       else:
           return ''

class DateTimeField(BaseField):

   def __init__( self, name, value=None):
       self.name = name
       self.value = value

   def get_html( self, prefix="", disabled=False ):
       html='\n\n<!-- earthsystem/datetime: begin -->\n'
       html=html+'\n<!-- earthsystem/datetime: begin -->\n\n'
       return html

   def set_size(self, size):
       self.size = int( size )

Let now implement the HTML rendering function in the actual get_html:

   def get_html( self, prefix="", disabled=False ):
       # Generate a local prefix in

  # order to ensure jQuery-UI compatibility

       localPrefix=prefix

       # Check if the local prefix is not null
       if localPrefix != "":
           # Add a p as first char
           localPrefix="p"+localPrefix

           # Replace the pipe with the underscore
           localPrefix=localPrefix.replace("|","_")
       else:
           # If there is no Galaxy prefix, use a dummy
           localPrefix="pXX_"

       # Perform the HTML rendering
       html='\n<!-- earthsystem/DateTime: begin -->\n'
       html=html+'<script>\n'
       html=html+'\n$(function() {\n'
       html=html+'\n$( "#%s%s" ).datepicker();\n'\
       % ( localPrefix, self.name)
       html=html+'\n$( "#%s%s" ).datepicker( "option", "dateFormat", "%s" );\n'\
       % ( localPrefix, self.name, self.format)
       html=html+'\n});\n'
       html=html+'</script>\n'

       # Till this code all is managed using local prefix
       html=html+'<input type="text" id="%s%s" name="%s%s" onchange="javascript:document.getElementById(\'%s%s\').value=this.value;" value="%s"%s >\n'\
       % ( localPrefix, self.name,localPrefix, self.name,prefix,self.name, escape( str( self.value ),  quote=True ), self.get_disabled_str( disabled ))

       # The hidden input field join the local prefix stuff with Galaxy param management
       html=html+'<input type="hidden" id="%s%s" name="%s%s" value="%s"%s>\n'\
       % ( prefix, self.name,prefix, self.name, escape( str( self.value ),  quote=True ), self.get_disabled_str( disabled ) )
       html=html+'\n<!-- earthsystem/DateTime: end -->\n\n'

       # Return the rendered code
       return html

Galaxy uses ordinary <input> HTML elements in order to fill tools parameters using the web user interface. So, ideally a parameter as <parm type=”datetime” name=”simStart” /> could be rendered as <input type=”text” name=”simStart” />. In order to have more parameters with the same name in the same web form or to provide parameters array support, Galaxy add a prefix to the name. The prefix could be an empty string if not needed (for example when you interact directly with the tool and no parameter array is needed) or a number followed by the pipee character “|” if the case of workflow setup or parameter array. So the final <input> element could be something as simStart or 32|simStart. This kind of identifier name is perfectly working in DHTML contest, but not allowed in Javascript. That means a workaround is needed in order to use jQuery UI components in Galaxy Tool interface.
The adopted solution is to use an hidden <input> element to perform the connection between user interface and the tool named in the usual Galaxy way. All the jQuery UI based stuff have to work with a local surrogate prefix. When the user ends the interaction with the jQuery UI, the result is copied in the hidden input element (cfr the onchange event).
In order to avoid omonimes, a local prefix is used even in the case of an empty Galaxy prefix.

Finally add the ToolParameter definition in the basic.py file:

# earthsystem: begin
from map import MapToolParameter
from datetime import DateTimeToolParameter
# earthsystem: end

parameter_types = dict( text            = TextToolParameter,
                       integer         = IntegerToolParameter,
                       float           = FloatToolParameter,
                       boolean         = BooleanToolParameter,
                       genomebuild     = GenomeBuildParameter,
                       select          = SelectToolParameter,
                       data_column     = ColumnListParameter,
                       hidden          = HiddenToolParameter,
                       baseurl         = BaseURLToolParameter,
                       file            = FileToolParameter,
                       ftpfile         = FTPFileToolParameter,
                       data            = DataToolParameter,
                       library_data    = LibraryDatasetToolParameter,
                       drill_down      = DrillDownSelectToolParameter,
# earthsystem: begin
                       map             = MapToolParameter,
                       datetime        = DateTimeToolParameter,
# earthsystem: end
)

To try the newly available tool parameter, let we use the following demo tool named datetime1.xml:

<tool id="DateTime1" name="Date Picker" force_history_refresh="True">
 <description>Pick a date</description>
 <command>echo $input1 2>&amp;1 >$out_file1</command>
 <inputs>
   <param format="yymmdd" name="input1" type="datetime" label="Select a date" value=""/>
 </inputs>
 <outputs>
   <data format="txt" name="out_file1" />
 </outputs>
 <help>DateTime Tool Parameter Demonstrator</help>
</tool>

Start Galaxy-ES as usually and try it! If everything works, your history will contain a text file with the date selected by the user. Try the DateTime tool in the following context: simple tool interaction, set in advance value in workflow, set at runtime workflow.

The parameter tool just added to Galaxy-ES is named DateTime, but actually it handles just Date. The following steps show how to add a jQuery UI plugin to the Galaxy-ES stack.

Download the http://trentrichardson.com/examples/timepicker/js/jquery-ui-timepicker-addon.js add on and save it in the galaxy-es/static/script directory

Activate the new UI component when the tool have to be managed during workflow editing: edit the file galaxy-es/templates/workflow/editor.mako and add the javascript reference (just the text in bold)

${h.js( "jquery",
           "jquery.tipsy",
           "jquery.event.drag",
           "jquery.event.drop",
           "jquery.event.hover",
           "jquery.form",
           "json2",
           "jstorage",
           "galaxy.base",
           "galaxy.workflow_editor.canvas",
           "jquery.autocomplete",
           "autocomplete_tagging",
           "jquery-ui-1.8.16.custom.min",
           "jquery-ui-timepicker-addon"
           )}

Activate the new UI component when the parameter have to be set in workflow execution: edit the run.mako file in the same directory and add the bold typed text where it is needed

<%def name="javascripts()">
   ${parent.javascripts()}
   ${h.js( "jquery.autocomplete", "jquery.tipsy", "jquery-ui-1.8.16.custom.min","jquery-ui-timepicker-addon" )}
   <script type="text/javascript">

Finally activate new new UI component when the parameter is managed in the tool user interface: edit the file galaxy-es/template/tool_form.mako and add the bold typed text where it is needed

<%def name="javascripts()">
   ${h.js( "jquery", "galaxy.panels", "galaxy.base", "jquery.autocomplete", "jstorage","jquery-ui-1.8.16.custom.min","jquery-ui-timepicker-addon" )}
   <script type="text/javascript">

Change the DateTimeToolParameter implementation in order to support options in JSON format and the working modes as datetime (default), date and time behaviours:

class DateTimeToolParameter( ToolParameter):
   def __init__( self, tool, elem ):
       ToolParameter.__init__( self, tool, elem )
       self.value = elem.get('value',"")
       self.mode = elem.get('mode',"datetime")
       self.options = elem.get('options',"")


   def get_html_field( self, trans=None, value=None, other_values={} ):
       if value is None: value = self.value

       return DateTimeField( self.name, self.mode, self.options,value)

   def get_initial_value( self, trans, context ):

       return self.value

More changes have to be implemented in DateTimeField class:

class DateTimeField(BaseField):

   def __init__( self, name, mode="datetime", options="", value=None, ):
       self.name = name
       self.options = options
       self.mode = mode
       self.value = value

The get_html method have to support the options management and provides the implementation of different tool parameter behaviours:

def get_html( self, prefix="", disabled=False ):
       # Generate a local prefix in order to ensure jQuery-UI compatibility
       localPrefix=prefix

       # Check if the local prefix is not null
       if localPrefix != "":
           # Add a p as first char
           localPrefix="p"+localPrefix

           # Replace the pipe with the underscore
           localPrefix=localPrefix.replace("|","_")
       else:
           # If there is no Galaxy prefix, use a dummy
           localPrefix="pXX_"

       #mode implementation

  picker="datetimepicker"


       if self.mode=='date':
           picker="datepicker"
       else:
           if self.mode=='time':
               picker='timepicker'

       # Perform the HTML rendering
       html='\n<!-- earthsystem/DateTime: begin -->\n'
       html=html+'<script>\n'
       html=html+'\n$(function() {\n'

       html=html+'\n$( "#%s%s" ).%s({%s});\n'\
       % ( localPrefix, self.name,picker,self.options)

       html=html+'\n});\n'
       html=html+'</script>\n'

       ...

       # Return the rendered code
       return html

The line

  html=html+'\n$( "#%s%s" ).%s({%s});\n'\

       % ( localPrefix, self.name,picker,self.options)
is very cryptic because everything is managed as a parameter:
The first two %s identifies the UI element with the localPrefix and name.
The third %s is the component name (datetimepicker|datepicker|timepicker)
Finally the last %s is a placeholder for the options.

With this DateTimeToolParameter implementation, the xml parm is described in the following way (modifie the datetime1.xml file):

<param mode="datetime" options="dateFormat:'yymmdd',separator:'Z',timeFormat:'hh',showMinute: false, stepHour: 1" name="input1" type="datetime" label="Select a date/time" value=""/>

The mode parameter could be datetime (default), date or time. The options is a JSON string. Refer to the original jQuery UI Datepicker (http://jqueryui.com/demos/datepicker/) and to the http://trentrichardson.com/examples/timepicker/ web site for more details.
Using this approach complex jQuery UI interfaces could wrap Galaxy-ES tools.
Comments