' % (self.toolId, batchargs)
+
+
+ self.extraGalaxyFn = {}
+
+# if hasattr(self.prototype, 'getExtraHistElements'):
+# for output in self.prototype.getExtraHistElements(choices):
+# if isinstance(output, HistElement):
+# self.extraGalaxyFn[output.name] = self.params[output.name]
+# else:
+# self.extraGalaxyFn[output[0]] = self.params[output[0]]
+
+ if hasattr(self.prototype, 'getExtraHistElements') and self.params.has_key('extra_output'):
+ extra_output = json.loads(unquote(self.params['extra_output']))
+ if isinstance(extra_output, list):
+ for output in extra_output:
+ if isinstance(output, HistElement):
+ self.extraGalaxyFn[unicode(output.name)] = self.params[output.name]
+ else:
+ self.extraGalaxyFn[unicode(output[0])] = self.params[output[0]]
+
+
+ username = self.params['userEmail'] if 'userEmail' in self.params else ''
+ self._executeTool(getClassName(self.prototype), choices, galaxyFn=self.jobFile, username=username)
+
+ if self.prototype.shouldAppendHtmlHeaderAndFooter(outputFormat):
+ print '''
+
+
+
+
+
+'''
+
+ def _executeTool(self, toolClassName, choices, galaxyFn, username):
+ if hasattr(super(GenericToolController, self), '_executeTool'):
+ super(GenericToolController, self)._executeTool(
+ toolClassName, choices, galaxyFn, username)
+
+ self._monkeyPatchAttr('extraGalaxyFn', self.extraGalaxyFn)
+ self._monkeyPatchAttr('runParams', self.json_params)
+ self.prototype.execute(choices, galaxyFn=galaxyFn, username=username)
+
+ def _monkeyPatchAttr(self, name, value):
+ if type(self.prototype).__name__ == 'type':
+ setattr(self.prototype, name, value)
+ else:
+ setattr(self.prototype.__class__, name, value)
+
+ def executeNoHistory(self):
+ html = self.prototype.execute(self.choices, None, self.galaxy.getUserName())
+ if not html:
+ html = 'Finished executing tool.'
+ return html
+
+ def isPublic(self):
+ try:
+ return self.prototype.isPublic()
+ except:
+ return False
+
+ def isDebugging(self):
+ try:
+ return self.prototype.isDebugMode()
+ except:
+ return False
+
+ def getIllustrationImage(self):
+ image = None
+ id = self.prototype.getToolIllustration()
+ if id:
+ image = self.STATIC_IMAGE_CLS(id)
+ return image
+
+ def getDemoURL(self):
+ try:
+ demo = self.prototype.getDemoSelections()
+ url = '?mako=generictool&tool_id=' + self.toolId
+ for i, id in enumerate(self.inputIds):
+ if self.inputTypes[i] == '__genome__':
+ id = 'dbkey'
+ #else:
+ # id = self.inputIds[i]
+ try:
+ val = getattr(demo, id)
+ except:
+ val = demo[i]
+ url += '&' + id + '=' + val
+ except Exception, e:
+ log.exception(e)
+ log.debug(i)
+ log.debug(repr(demo))
+ url = None
+
+ return url
+
+ def hasDemoURL(self):
+ try:
+ demo = self.prototype.getDemoSelections()
+ if len(demo) > 0:
+ return True
+ except Exception, e:
+ log.exception(e)
+ return False
+
+ def getFullExampleURL(self):
+ return self.prototype.getFullExampleURL()
+
+ def hasFullExampleURL(self):
+ try:
+ url = self.prototype.getFullExampleURL()
+ if url is not None:
+ return True
+ except Exception, e:
+ log.exception(e)
+ return False
+
+ def isRedirectTool(self):
+ try:
+ return self.prototype.isRedirectTool(self.choices)
+ except TypeError:
+ return self.prototype.isRedirectTool()
+
+ def doRedirect(self):
+ return self.isRedirectTool() and self.getRedirectURL() and self.params.has_key('start')
+
+ def getRedirectURL(self):
+ return self.prototype.getRedirectURL(self.choices)
+
+ def validate(self):
+ #ChoiceTuple = namedtuple('ChoiceTuple', self.inputIds)
+ #self.choices = ChoiceTuple._make(self.inputValues)
+ self.errorMessage = self.prototype.validateAndReturnErrors(self.choices)
+
+ def isValid(self):
+ return True if self.errorMessage is None else False
+
+ def hasErrorMessage(self):
+ return False if self.errorMessage in [None, ''] else True
+
+ #jsonMethods = ('ajaxValidate')
+ #def ajaxValidate(self):
+ # return self.prototype.validateAndReturnErrors(self.inputValues)
+
+ def getInputValueForTrack(self, id, name):
+ return None
+
+
+def getController(transaction=None, job=None):
+ control = GenericToolController(transaction, job)
+ return control
diff --git a/lib/proto/hyper_gui.py b/lib/proto/gui.py
similarity index 89%
rename from lib/proto/hyper_gui.py
rename to lib/proto/gui.py
index d7f1ce09a6a6..85f114ab41f7 100644
--- a/lib/proto/hyper_gui.py
+++ b/lib/proto/gui.py
@@ -162,44 +162,44 @@ def getUserName(self):
def getUserIP(self):
return self.trans.environ['REMOTE_ADDR']
- def getSessionKey(self):
- session = self.trans.get_galaxy_session()
-# key = session.session_key if session.is_valid and session.user_id else None
- key = session.session_key if session.is_valid else None
- return key
-
- def hasSessionParam(self, param):
- user = self.trans.get_user()
- if user and user.preferences.has_key('hb_' + param):
-# hbdict = from_json_string(user.preferences['hyperbrowser'])
-# if hbdict.has_key(param):
- return True
- return False
-
- def getSessionParam(self, param):
- prefs = self.trans.get_user().preferences
- value = from_json_string(prefs['hb_'+param])
- return value
-
- def setSessionParam(self, param, value):
- if self.trans.get_user():
- prefs = self.trans.get_user().preferences
- #hbdict = dict()
- #hbdict[param] = value
- prefs['hb_'+param] = to_json_string(value)
- self.trans.sa_session.flush()
-
+# def getSessionKey(self):
+# session = self.trans.get_galaxy_session()
+# # key = session.session_key if session.is_valid and session.user_id else None
+# key = session.session_key if session.is_valid else None
+# return key
+#
+# def hasSessionParam(self, param):
+# user = self.trans.get_user()
+# if user and user.preferences.has_key('hb_' + param):
+# return True
+# return False
+#
+# def getSessionParam(self, param):
+# prefs = self.trans.get_user().preferences
+# value = from_json_string(prefs['hb_'+param])
+# return value
+#
+# def setSessionParam(self, param, value):
+# if self.trans.get_user():
+# prefs = self.trans.get_user().preferences
+# #hbdict = dict()
+# #hbdict[param] = value
+# prefs['hb_'+param] = to_json_string(value)
+# self.trans.sa_session.flush()
def selected(opt, sel):
return ' selected="selected" ' if opt == sel else ''
+
def checked(opt, sel):
return ' checked="checked" ' if opt == sel else ''
+
def disabled(opt, sel):
return ' disabled="disabled" ' if opt == sel else ''
+
def _disabled(opt, sel):
return ' disabled="disabled" ' if opt != sel else ''
diff --git a/lib/proto/hyperbrowser/gmapallinfo.py b/lib/proto/hyperbrowser/gmapallinfo.py
index 3be257fd7c07..a5e3ef9bbfd4 100644
--- a/lib/proto/hyperbrowser/gmapallinfo.py
+++ b/lib/proto/hyperbrowser/gmapallinfo.py
@@ -1,7 +1,7 @@
from gold.application.GalaxyInterface import GalaxyInterface
import quick.extra.GoogleMapsInterface as GMI
-from proto.hyper_gui import *
+from proto.gui import *
from proto.BaseToolController import *
from proto.hyperbrowser.HyperBrowserControllerMixin import HyperBrowserControllerMixin
diff --git a/lib/proto/hyperbrowser/hyper_gui.py b/lib/proto/hyperbrowser/hyper_gui.py
index 719a310b222a..93780b1457cf 100644
--- a/lib/proto/hyperbrowser/hyper_gui.py
+++ b/lib/proto/hyperbrowser/hyper_gui.py
@@ -1,8 +1,8 @@
#note cannot import HB.GalaxyInterface here due to rpy threading issue
-from proto.hyper_gui import *
-from proto.hyper_gui import _disabled
+from proto.gui import *
+from proto.gui import _disabled
class TrackWrapper:
diff --git a/lib/proto/tools/FileImport.py b/lib/proto/tools/FileImport.py
index 3a50317f1a20..654fe105d9a4 100644
--- a/lib/proto/tools/FileImport.py
+++ b/lib/proto/tools/FileImport.py
@@ -9,16 +9,18 @@
class FileImport(GeneralGuiTool):
- @staticmethod
- def getToolName():
+ @classmethod
+ def getToolName(cls):
"""
Specifies a header of the tool, which is displayed at the top of the
page.
+
+ Mandatory method for all ProTo tools.
"""
return "Import file to history"
- @staticmethod
- def getInputBoxNames():
+ @classmethod
+ def getInputBoxNames(cls):
"""
Specifies a list of headers for the input boxes, and implicitly also
the number of input boxes to display on the page. The returned list
@@ -35,24 +37,28 @@ def getInputBoxNames():
Note: the key has to be camelCase and start with a non-capital letter
(e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
"""
return [('', 'basicQuestionId'),
('Input filename', 'input'),
('Format', 'format'),
('Datatype', 'datatype')]
- # @staticmethod
- # def getInputBoxOrder():
+ # @classmethod
+ # def getInputBoxOrder(cls):
# """
# Specifies the order in which the input boxes should be displayed,
# as a list. The input boxes are specified by index (starting with 1)
# or by key. If None, the order of the input boxes is in the order
- # specified by getInputBoxNames.
+ # specified by getInputBoxNames().
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
#
- # @staticmethod
- # def getInputBoxGroups(choices=None):
+ # @classmethod
+ # def getInputBoxGroups(cls, choices=None):
# """
# Creates a visual separation of groups of consecutive option boxes
# from the rest (fieldset). Each such group has an associated label
@@ -61,23 +67,30 @@ def getInputBoxNames():
# (or index) of the first and last options boxes (inclusive).
#
# Example:
- # from quick.webtool.GeneralGuiTool import BoxGroup
+ # from proto.tools.GeneralGuiTool import BoxGroup
# return [BoxGroup(label='A group of choices', first='firstKey',
# last='secondKey')]
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
- @staticmethod
- def getOptionsBoxBasicQuestionId(): # Alternatively: getOptionsBox1()
+ @classmethod
+ def getOptionsBoxBasicQuestionId(cls): # Alt: getOptionsBox1()
"""
Defines the type and contents of the input box. User selections are
returned to the tools in the prevChoices and choices attributes to
other methods. These are lists of results, one for each input box
(in the order specified by getInputBoxOrder()).
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
The input box is defined according to the following syntax:
- Selection box: ['choice1','choice2']
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
- Returns: string
Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
@@ -102,14 +115,17 @@ def getOptionsBoxBasicQuestionId(): # Alternatively: getOptionsBox1()
History selection box: ('__history__',) |
('__history__', 'bed', 'wig')
- Only history items of specified types are shown.
- - Returns: colon-separated string denoting galaxy track name, as
- specified in ExternalTrackManager.py.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
History check box list: ('__multihistory__', ) |
('__multihistory__', 'bed', 'wig')
- Only history items of specified types are shown.
- - Returns: OrderedDict with galaxy id as key and galaxy track name
- as value if checked, else None.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
Hidden field: ('__hidden__', 'Hidden value')
- Returns: string
@@ -121,15 +137,42 @@ def getOptionsBoxBasicQuestionId(): # Alternatively: getOptionsBox1()
Check box list: OrderedDict([('key1', True), ('key2', False),
('key3', False)])
- Returns: OrderedDict from key to selection status (bool).
- """
- return '__hidden__', ''
- @staticmethod
- def getOptionsBoxInput(prevChoices): # Alternatively: getOptionsBox2()
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
return '__hidden__', ''
- @staticmethod
- def getOptionsBoxDatatype(prevChoices):
+ @classmethod
+ def getOptionsBoxInput(cls, prevChoices): # Alt: getOptionsBox2()
"""
See getOptionsBoxFirstKey().
@@ -138,28 +181,40 @@ def getOptionsBoxDatatype(prevChoices):
in this case). The elements can accessed either by index, e.g.
prevChoices[0] for the result of input box 1, or by key, e.g.
prevChoices.key (case 2).
+
+ Mandatory for the subsequent keys (after the first key) defined in
+ getInputBoxNames(), if any.
"""
+ return '__hidden__', ''
+
+ @staticmethod
+ def getOptionsBoxDatatype(prevChoices):
+
return '__hidden__', prevChoices.format if prevChoices.format else 'bed'
@staticmethod
def getOptionsBoxFormat(prevChoices):
return '__hidden__', ''
- # @staticmethod
- # def getInfoForOptionsBoxKey(prevChoices):
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
# """
# If not None, defines the string content of an clickable info box
# beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
#
- # @staticmethod
- # def getDemoSelections():
+ # @classmethod
+ # def getDemoSelections(cls):
# """
# Defines a set of demo inputs to the option boxes in the
# order defined by getOptionBoxNames and getOptionsBoxOrder.
# If not None, a Demo button appears in the interface. Clicking the
# button fills the option boxed with the defined demo values.
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return ['testChoice1', '..']
#
@@ -170,7 +225,7 @@ def getOptionsBoxFormat(prevChoices):
# This is defined by a list of HistElement objects, as in the
# following example:
#
- # from proto.GeneralGuiTool import HistElement
+ # from proto.tools.GeneralGuiTool import HistElement
# return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
#
# It is good practice to use class constants for longer strings.
@@ -179,19 +234,23 @@ def getOptionsBoxFormat(prevChoices):
# the dataset referred to by the extra history element. To fetch the
# path, use the dict cls.extraGalaxyFn with the defined history title
# as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
- @staticmethod
- def execute(choices, galaxyFn=None, username=''):
+ @classmethod
+ def execute(cls, choices, galaxyFn=None, username=''):
"""
Is called when execute-button is pushed by web-user. Should print
output as HTML to standard out, which will be directed to a results
page in Galaxy history. If getOutputFormat is anything else than
- HTML, the output should be written to the file with path galaxyFn.
+ 'html', the output should be written to the file with path galaxyFn.
If needed, StaticFile can be used to get a path where additional
- files can be put (e.g. generated image files). choices is a list of
- selections made by web-user in each options box.
+ files can be put (cls, e.g. generated image files). choices is a list
+ of selections made by web-user in each options box.
+
+ Mandatory unless isRedirectTool() returns True.
"""
input = str(choices.input)
@@ -210,7 +269,7 @@ def execute(choices, galaxyFn=None, username=''):
input = os.path.sep.join([GALAXY_BASE_DIR.rstrip(os.path.sep),
input.lstrip(os.path.sep)])
- datatype = choices.format if choices.format else choices.datatype
+ # datatype = choices.format if choices.format else choices.datatype
# if input.endswith('.' + datatype):
shutil.copy(input, output)
@@ -220,8 +279,8 @@ def execute(choices, galaxyFn=None, username=''):
# raise Exception(input + ' not allowed to import!')
- @staticmethod
- def validateAndReturnErrors(choices):
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
"""
Should validate the selected input parameters. If the parameters are
not valid, an error text explaining the problem should be returned.
@@ -229,49 +288,61 @@ def validateAndReturnErrors(choices):
out the execute button (even if the text is empty). If all
parameters are valid, the method should return None, which enables
the execute button.
+
+ Optional method. Default return value if method is not defined: None
"""
return ''
- # @staticmethod
- # def getSubToolClasses():
+ # @classmethod
+ # def getSubToolClasses(cls):
# """
# Specifies a list of classes for subtools of the main tool. These
# subtools will be selectable from a selection box at the top of the
# page. The input boxes will change according to which subtool is
# selected.
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
#
- # @staticmethod
- # def isPublic():
+ # @classmethod
+ # def isPublic(cls):
# """
# Specifies whether the tool is accessible to all users. If False, the
- # tool is only accessible to a restricted set of users as defined in
- # LocalOSConfig.py.
+ # tool is only accessible to a restricted set of users as well as admin
+ # users, as defined in the galaxy.ini file.
+ #
+ # Optional method. Default return value if method is not defined: False
# """
# return False
#
- # @staticmethod
- # def isRedirectTool():
+ # @classmethod
+ # def isRedirectTool(cls):
# """
# Specifies whether the tool should redirect to an URL when the Execute
# button is clicked.
+ #
+ # Optional method. Default return value if method is not defined: False
# """
# return False
#
- # @staticmethod
- # def getRedirectURL(choices):
+ # @classmethod
+ # def getRedirectURL(cls, choices):
# """
# This method is called to return an URL if the isRedirectTool method
# returns True.
+ #
+ # Mandatory method if isRedirectTool() returns True.
# """
# return ''
#
- # @staticmethod
- # def isHistoryTool():
+ # @classmethod
+ # def isHistoryTool(cls):
# """
# Specifies if a History item should be created when the Execute button
# is clicked.
+ #
+ # Optional method. Default return value if method is not defined: True
# """
# return True
#
@@ -284,11 +355,14 @@ def validateAndReturnErrors(choices):
# """
# return cls.isHistoryTool()
#
- # @staticmethod
- # def isDynamic():
+ # @classmethod
+ # def isDynamic(cls):
# """
- # Specifies whether changing the content of texboxes causes the page to
- # reload.
+ # Specifies whether changing the content of textboxes causes the page
+ # to reload. Returning False stops the need for reloading the tool
+ # after each input, resulting in less lags for the user.
+ #
+ # Optional method. Default return value if method is not defined: True
# """
# return True
#
@@ -298,42 +372,83 @@ def validateAndReturnErrors(choices):
# Specifies a list of input boxes which resets the subsequent stored
# choices previously made. The input boxes are specified by index
# (starting with 1) or by key.
+ #
+ # Optional method. Default return value if method is not defined: True
# """
# return []
#
- # @staticmethod
- # def getToolDescription():
+ # @classmethod
+ # def getToolDescription(cls):
# """
# Specifies a help text in HTML that is displayed below the tool.
+ #
+ # Optional method. Default return value if method is not defined: ''
# """
# return ''
#
- # @staticmethod
- # def getToolIllustration():
+ # @classmethod
+ # def getToolIllustration(cls):
# """
- # Specifies an id used by StaticFile.py to reference an illustration file
- # on disk. The id is a list of optional directory names followed by a file
- # name. The base directory is STATIC_PATH as defined by Config.py. The
- # full path is created from the base directory followed by the id.
+ # Specifies an id used by StaticFile.py to reference an illustration
+ # file on disk. The id is a list of optional directory names followed
+ # by a filename. The base directory is STATIC_PATH as defined by
+ # Config.py. The full path is created from the base directory
+ # followed by the id.
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
#
- # @staticmethod
- # def getFullExampleURL():
+ # @classmethod
+ # def getFullExampleURL(cls):
# """
# Specifies an URL to an example page that describes the tool, for
# instance a Galaxy page.
+ #
+ # Optional method. Default return value if method is not defined: None
# """
# return None
#
- # @staticmethod
- # def isDebugMode():
+ # @classmethod
+ # def isDebugMode(cls):
# """
- # Specifies whether the debug mode is turned on.
+ # Specifies whether the debug mode is turned on. Debug mode is
+ # currently mostly used within the Genomic HyperBrowser and will make
+ # little difference in a plain Galaxy ProTo installation.
+ #
+ # Optional method. Default return value if method is not defined: False
# """
# return False
+
+ @classmethod
+ def getOutputFormat(cls, choices):
+ """
+ The format of the history element with the output of the tool. Note
+ that if 'html' is returned, any print statements in the execute()
+ method is printed to the output dataset. For text-based output
+ (e.g. bed) the output dataset only contains text written to the
+ galaxyFn file, while all print statements are redirected to the info
+ field of the history item box.
+
+ Note that for 'html' output, standard HTML header and footer code is
+ added to the output dataset. If one wants to write the complete HTML
+ page, use the restricted output format 'customhtml' instead.
+
+ Optional method. Default return value if method is not defined:
+ 'html'
+ """
+ return choices.format if choices.format else choices.datatype
+
+ # @classmethod
+ # def getOutputName(cls, choices=None):
+ # """
+ # The title (name) of the main output history element.
#
+ # Optional method. Default return value if method is not defined:
+ # the name of the tool.
+ # """
+ # return cls.getToolSelectionName()
@staticmethod
- def getOutputFormat(choices):
- return choices.format if choices.format else choices.datatype
+ def shouldAppendHtmlHeaderAndFooter(outputFormat):
+ return False
diff --git a/lib/proto/tools/GeneralGuiTool.py b/lib/proto/tools/GeneralGuiTool.py
index 8188ecb24002..5b4d490e82dd 100644
--- a/lib/proto/tools/GeneralGuiTool.py
+++ b/lib/proto/tools/GeneralGuiTool.py
@@ -89,6 +89,10 @@ def getOutputName(cls, choices=None):
def validateAndReturnErrors(choices):
return None
+ @staticmethod
+ def shouldAppendHtmlHeaderAndFooter(outputFormat):
+ return outputFormat == 'html'
+
# Convenience methods
@classmethod
diff --git a/lib/proto/tools/GenerateToolsTool.py b/lib/proto/tools/GenerateToolsTool.py
index 2e014e8759d8..492d80e9441f 100644
--- a/lib/proto/tools/GenerateToolsTool.py
+++ b/lib/proto/tools/GenerateToolsTool.py
@@ -106,8 +106,6 @@ def _setupExtraBoxMethods(cls):
setattr(cls, 'getOptionsBoxNewDir%s' % i,
partial(cls._getOptionsBoxNewDir, index=i))
- from gold.application.LogSetup import logMessage
-
@classmethod
def _getProtoRelToolDirs(cls):
assert cls.TOOL_DIR.startswith(SOURCE_CODE_BASE_DIR)
@@ -232,7 +230,7 @@ def getToolDescription():
"with 'Tool', e.g. 'MyNewTool'. This will create "
"a Python module 'MyNewTool.py' with the class "
"'MyNewTool', inheriting from "
- "'proto.GeneralGuiTool'.", emphasize=True)
+ "'proto.tools.GeneralGuiTool'.", emphasize=True)
core.descriptionLine("Tool name",
"A string with the name or title of the tool. "
"This will appear on the top of the tool GUI "
diff --git a/lib/proto/tools/ToolTemplate.py b/lib/proto/tools/ToolTemplate.py
index 6f8f989a714a..74ed43fdad26 100644
--- a/lib/proto/tools/ToolTemplate.py
+++ b/lib/proto/tools/ToolTemplate.py
@@ -58,7 +58,7 @@ def getInputBoxNames(cls):
# (or index) of the first and last options boxes (inclusive).
#
# Example:
- # from quick.webtool.GeneralGuiTool import BoxGroup
+ # from proto.tools.GeneralGuiTool import BoxGroup
# return [BoxGroup(label='A group of choices', first='firstKey',
# last='secondKey')]
#
@@ -78,7 +78,10 @@ def getOptionsBoxFirstKey(cls): # Alt: getOptionsBox1()
The input box is defined according to the following syntax:
- Selection box: ['choice1','choice2']
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
- Returns: string
Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
@@ -204,7 +207,7 @@ def getOptionsBoxSecondKey(cls, prevChoices): # Alt: getOptionsBox2()
# This is defined by a list of HistElement objects, as in the
# following example:
#
- # from proto.GeneralGuiTool import HistElement
+ # from proto.tools.GeneralGuiTool import HistElement
# return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
#
# It is good practice to use class constants for longer strings.
@@ -398,10 +401,10 @@ def validateAndReturnErrors(cls, choices):
#
# @classmethod
# def getOutputName(cls, choices=None):
- # return cls.getToolSelectionName()
# """
# The title (name) of the main output history element.
#
# Optional method. Default return value if method is not defined:
# the name of the tool.
# """
+ # return cls.getToolSelectionName()
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool1.py b/lib/proto/tools/guitest/ProtoGuiTestTool1.py
new file mode 100644
index 000000000000..4260c643924a
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool1.py
@@ -0,0 +1,481 @@
+from collections import OrderedDict
+
+from proto.HtmlCore import HtmlCore
+from proto.tools.GeneralGuiTool import GeneralGuiTool
+
+ALL_GUI_ELEMENTS = [
+ ('Check box', 'checkBox'),
+ ('Selection box', 'selectionBox'),
+ ('Selection box (empty)', 'selectionBoxEmpty'),
+ ('Text area (simple, non-dynamic)', 'textAreaSimple'),
+ ('Text area (medium, with default value, non-dynamic)', 'textAreaMediumWithDefault'),
+ ('Text area (large, readonly)', 'textAreaLargeReadonly'),
+ ('Password field', 'passwordField'),
+ ('Raw HTML', 'rawHtml'),
+ ('Table', 'table'),
+ ('Check box list', 'checkBoxList'),
+ ('Genome selection box', 'genomeSelection'),
+ ('History selection box', 'historySelection'),
+ ('History selection box (tabular files only)', 'historySelectionTabular'),
+ ('History check box list', 'historyCheckBoxList'),
+ ('History check box list (tabular files only)', 'historyCheckBoxListTabular')
+]
+
+SELECTION_A = 'Selection A'
+SELECTION_B = 'Selection B'
+SELECTION_C = 'Selection C'
+DEFAULT_TEXT = 'Default text'
+READ_ONLY_TEXT = "Read only text"
+TABLE = [['Header A', 'Header B'], [1, 2], ['Some text', 'Other text']]
+CHECK_BOX_LIST = OrderedDict([('Something', True), ('Something else', False)])
+
+
+class ProtoGuiTestTool1(GeneralGuiTool):
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Basic GUI elements: Test tool #1 for Galaxy ProTo GUI"
+
+ @classmethod
+ def getInputBoxNames(cls):
+ """
+ Specifies a list of headers for the input boxes, and implicitly also
+ the number of input boxes to display on the page. The returned list
+ can have two syntaxes:
+
+ 1) A list of strings denoting the headers for the input boxes in
+ numerical order.
+ 2) A list of tuples of strings, where each tuple has
+ two items: a header and a key.
+
+ The contents of each input box must be defined by the function
+ getOptionsBoxK, where K is either a number in the range of 1 to the
+ number of boxes (case 1), or the specified key (case 2).
+
+ Note: the key has to be camelCase and start with a non-capital letter
+ (e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
+ """
+ return ALL_GUI_ELEMENTS
+
+ # @classmethod
+ # def getInputBoxOrder(cls):
+ # """
+ # Specifies the order in which the input boxes should be displayed,
+ # as a list. The input boxes are specified by index (starting with 1)
+ # or by key. If None, the order of the input boxes is in the order
+ # specified by getInputBoxNames().
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getInputBoxGroups(cls, choices=None):
+ # """
+ # Creates a visual separation of groups of consecutive option boxes
+ # from the rest (fieldset). Each such group has an associated label
+ # (string), which is shown to the user. To define groups of option
+ # boxes, return a list of BoxGroup namedtuples with the label, the key
+ # (or index) of the first and last options boxes (inclusive).
+ #
+ # Example:
+ # from proto.tools.GeneralGuiTool import BoxGroup
+ # return [BoxGroup(label='A group of choices', first='firstKey',
+ # last='secondKey')]
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def getOptionsBoxCheckBox(cls): # Alt: getOptionsBox1()
+ """
+ Defines the type and contents of the input box. User selections are
+ returned to the tools in the prevChoices and choices attributes to
+ other methods. These are lists of results, one for each input box
+ (in the order specified by getInputBoxOrder()).
+
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
+ The input box is defined according to the following syntax:
+
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
+ - Returns: string
+
+ Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
+ - Tuple syntax: (contents, height (#lines) = 1, read only flag = False)
+ - The contents is the default value shown inside the text area
+ - Returns: string
+
+ Raw HTML code: '__rawstr__', 'HTML code'
+ - This is mainly intended for read only usage. Even though more
+ advanced hacks are possible, it is discouraged.
+
+ Password field: '__password__'
+ - Returns: string
+
+ Genome selection box: '__genome__'
+ - Returns: string
+
+ History selection box: ('__history__',) |
+ ('__history__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
+
+ History check box list: ('__multihistory__', ) |
+ ('__multihistory__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
+
+ Hidden field: ('__hidden__', 'Hidden value')
+ - Returns: string
+
+ Table: [['header1','header2'], ['cell1_1','cell1_2'],
+ ['cell2_1','cell2_2']]
+ - Returns: None
+
+ Check box list: OrderedDict([('key1', True), ('key2', False),
+ ('key3', False)])
+ - Returns: OrderedDict from key to selection status (bool).
+
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
+ return True
+
+ @classmethod
+ def getOptionsBoxSelectionBox(cls, prevChoices): # Alt: getOptionsBox2()
+ """
+ See getOptionsBoxFirstKey().
+
+ prevChoices is a namedtuple of selections made by the user in the
+ previous input boxes (that is, a namedtuple containing only one element
+ in this case). The elements can accessed either by index, e.g.
+ prevChoices[0] for the result of input box 1, or by key, e.g.
+ prevChoices.key (case 2).
+
+ Mandatory for the subsequent keys (after the first key) defined in
+ getInputBoxNames(), if any.
+ """
+ return [SELECTION_A, SELECTION_B, SELECTION_C]
+
+ @classmethod
+ def getOptionsBoxSelectionBoxEmpty(cls, prevChoices): # Alt: getOptionsBox2()
+ return []
+
+ @classmethod
+ def getOptionsBoxTextAreaSimple(cls, prevChoices):
+ return ''
+
+ @classmethod
+ def getOptionsBoxTextAreaMediumWithDefault(cls, prevChoices):
+ return DEFAULT_TEXT, 3
+
+ @classmethod
+ def getOptionsBoxTextAreaLargeReadonly(cls, prevChoices):
+ return READ_ONLY_TEXT, 5, True
+
+ @classmethod
+ def getOptionsBoxPasswordField(cls, prevChoices):
+ return '__password__'
+
+ @classmethod
+ def getOptionsBoxRawHtml(cls, prevChoices):
+ core = HtmlCore()
+ core.image('static/images/pearson.png')
+ return '__rawstr__', str(core)
+
+ @classmethod
+ def getOptionsBoxTable(cls, prevChoices):
+ return TABLE
+
+ @classmethod
+ def getOptionsBoxCheckBoxList(cls, prevChoices):
+ return CHECK_BOX_LIST
+
+ @classmethod
+ def getOptionsBoxGenomeSelection(cls, prevChoices):
+ return '__genome__'
+
+ @classmethod
+ def getOptionsBoxHistorySelection(cls, prevChoices):
+ return '__history__',
+
+ @classmethod
+ def getOptionsBoxHistorySelectionTabular(cls, prevChoices):
+ return '__history__', 'tabular'
+
+ @classmethod
+ def getOptionsBoxHistoryCheckBoxList(cls, prevChoices):
+ return '__multihistory__',
+
+ @classmethod
+ def getOptionsBoxHistoryCheckBoxListTabular(cls, prevChoices):
+ return '__multihistory__', 'tabular'
+
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
+ # """
+ # If not None, defines the string content of an clickable info box
+ # beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getDemoSelections(cls):
+ # """
+ # Defines a set of demo inputs to the option boxes in the
+ # order defined by getOptionBoxNames and getOptionsBoxOrder.
+ # If not None, a Demo button appears in the interface. Clicking the
+ # button fills the option boxed with the defined demo values.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return ['testChoice1', '..']
+ #
+ # @classmethod
+ # def getExtraHistElements(cls, choices):
+ # """
+ # Defines extra history elements to be created when clicking execute.
+ # This is defined by a list of HistElement objects, as in the
+ # following example:
+ #
+ # from proto.tools.GeneralGuiTool import HistElement
+ # return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
+ #
+ # It is good practice to use class constants for longer strings.
+ #
+ # In the execute() method, one typically needs to fetch the path to
+ # the dataset referred to by the extra history element. To fetch the
+ # path, use the dict cls.extraGalaxyFn with the defined history title
+ # as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def execute(cls, choices, galaxyFn=None, username=''):
+ """
+ Is called when execute-button is pushed by web-user. Should print
+ output as HTML to standard out, which will be directed to a results
+ page in Galaxy history. If getOutputFormat is anything else than
+ 'html', the output should be written to the file with path galaxyFn.
+ If needed, StaticFile can be used to get a path where additional
+ files can be put (cls, e.g. generated image files). choices is a list
+ of selections made by web-user in each options box.
+
+ Mandatory unless isRedirectTool() returns True.
+ """
+ pass
+
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ core = HtmlCore()
+ core.smallHeader('GUI selections (value of prevChoices/choices attributes)')
+ for guiElement in ALL_GUI_ELEMENTS:
+ core.descriptionLine(guiElement[0] + ' [' + guiElement[1] + ']',
+ repr(getattr(choices, guiElement[1])))
+ return str(core)
+
+ # @classmethod
+ # def getSubToolClasses(cls):
+ # """
+ # Specifies a list of classes for subtools of the main tool. These
+ # subtools will be selectable from a selection box at the top of the
+ # page. The input boxes will change according to which subtool is
+ # selected.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ # @classmethod
+ # def isRedirectTool(cls):
+ # """
+ # Specifies whether the tool should redirect to an URL when the Execute
+ # button is clicked.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getRedirectURL(cls, choices):
+ # """
+ # This method is called to return an URL if the isRedirectTool method
+ # returns True.
+ #
+ # Mandatory method if isRedirectTool() returns True.
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def isHistoryTool(cls):
+ # """
+ # Specifies if a History item should be created when the Execute button
+ # is clicked.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ @classmethod
+ def isDynamic(cls):
+ """
+ Specifies whether changing the content of textboxes causes the page
+ to reload. Returning False stops the need for reloading the tool
+ after each input, resulting in less lags for the user.
+
+ Optional method. Default return value if method is not defined: True
+ """
+ return False
+ #
+ # @classmethod
+ # def getResetBoxes(cls):
+ # """
+ # Specifies a list of input boxes which resets the subsequent stored
+ # choices previously made. The input boxes are specified by index
+ # (starting with 1) or by key.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return []
+ #
+ # @classmethod
+ # def getToolDescription(cls):
+ # """
+ # Specifies a help text in HTML that is displayed below the tool.
+ #
+ # Optional method. Default return value if method is not defined: ''
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def getToolIllustration(cls):
+ # """
+ # Specifies an id used by StaticFile.py to reference an illustration
+ # file on disk. The id is a list of optional directory names followed
+ # by a filename. The base directory is STATIC_PATH as defined by
+ # Config.py. The full path is created from the base directory
+ # followed by the id.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getFullExampleURL(cls):
+ # """
+ # Specifies an URL to an example page that describes the tool, for
+ # instance a Galaxy page.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def isDebugMode(cls):
+ # """
+ # Specifies whether the debug mode is turned on. Debug mode is
+ # currently mostly used within the Genomic HyperBrowser and will make
+ # little difference in a plain Galaxy ProTo installation.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getOutputFormat(cls, choices):
+ # """
+ # The format of the history element with the output of the tool. Note
+ # that if 'html' is returned, any print statements in the execute()
+ # method is printed to the output dataset. For text-based output
+ # (e.g. bed) the output dataset only contains text written to the
+ # galaxyFn file, while all print statements are redirected to the info
+ # field of the history item box.
+ #
+ # Note that for 'html' output, standard HTML header and footer code is
+ # added to the output dataset. If one wants to write the complete HTML
+ # page, use the restricted output format 'customhtml' instead.
+ #
+ # Optional method. Default return value if method is not defined:
+ # 'html'
+ # """
+ # return 'html'
+ #
+ # @classmethod
+ # def getOutputName(cls, choices=None):
+ # """
+ # The title (name) of the main output history element.
+ #
+ # Optional method. Default return value if method is not defined:
+ # the name of the tool.
+ # """
+ # return cls.getToolSelectionName()
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool1.xml b/lib/proto/tools/guitest/ProtoGuiTestTool1.xml
new file mode 100644
index 000000000000..cff1dc990b21
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool1.xml
@@ -0,0 +1,4 @@
+
+ Test tool #1 for Galaxy ProTo GUI
+
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool2.py b/lib/proto/tools/guitest/ProtoGuiTestTool2.py
new file mode 100644
index 000000000000..2ef29d4791a9
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool2.py
@@ -0,0 +1,508 @@
+from collections import OrderedDict
+
+from proto.HtmlCore import HtmlCore
+from proto.tools.GeneralGuiTool import GeneralGuiTool
+
+ALL_GUI_ELEMENTS = [
+ ('Password field', 'passwordField'),
+ ('Raw HTML (hidden until password is entered)', 'rawHtmlWaitForPassword'),
+ ('History selection box (tabular files only)', 'historySelectionTabular'),
+ ('History contents (10 first lines)', 'historyContents'),
+ ('Show extra fields', 'checkBox'),
+ ('Selection box', 'selectionBox'),
+ ('Text area (readandwrite)', 'textAreaReadWrite'),
+ ('Text area (readonly)', 'textAreaReadonly'),
+ ('Table', 'table'),
+ ('Check box list (only unique values)', 'checkBoxList'),
+ ('Hidden element', 'hidden')
+]
+
+# Order is different than
+GUI_ELEMENTS_ORDER = [
+ 'checkBox',
+ 'selectionBox',
+ 'textAreaReadWrite',
+ 'textAreaReadonly',
+ 'passwordField',
+ 'rawHtmlWaitForPassword',
+ 'table',
+ 'checkBoxList',
+ 'hidden',
+ 'historySelectionTabular',
+ 'historyContents'
+]
+
+A = 'A'
+B = 'B'
+C = 'C'
+DEFAULT_TEXT = 'Default text'
+READ_ONLY_TEXT = "Read only text"
+CHECK_BOX_LIST = OrderedDict([('Something', True), ('Something else', False)])
+
+
+class ProtoGuiTestTool2(GeneralGuiTool):
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Dynamic GUI dependencies: Test tool #2 for Galaxy ProTo GUI"
+
+ @classmethod
+ def getInputBoxNames(cls):
+ """
+ Specifies a list of headers for the input boxes, and implicitly also
+ the number of input boxes to display on the page. The returned list
+ can have two syntaxes:
+
+ 1) A list of strings denoting the headers for the input boxes in
+ numerical order.
+ 2) A list of tuples of strings, where each tuple has
+ two items: a header and a key.
+
+ The contents of each input box must be defined by the function
+ getOptionsBoxK, where K is either a number in the range of 1 to the
+ number of boxes (case 1), or the specified key (case 2).
+
+ Note: the key has to be camelCase and start with a non-capital letter
+ (e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
+ """
+ return ALL_GUI_ELEMENTS
+
+ @classmethod
+ def getInputBoxOrder(cls):
+ """
+ Specifies the order in which the input boxes should be displayed,
+ as a list. The input boxes are specified by index (starting with 1)
+ or by key. If None, the order of the input boxes is in the order
+ specified by getInputBoxNames().
+
+ Optional method. Default return value if method is not defined: None
+ """
+
+ # Order is different than in getInputBoxNames() as getResetBoxes() is set.
+ # This is because reset boxes (in this case 'selectionBox') will reset all subsequent
+ # option boxes in the order defined in getInputBoxNames(). Thus, if one wants to
+ # hinder reset of boxes further down on the GUI, the boxes need to be rearranged here.
+ return GUI_ELEMENTS_ORDER
+
+ @classmethod
+ def getInputBoxGroups(cls, choices=None):
+ """
+ Creates a visual separation of groups of consecutive option boxes
+ from the rest (fieldset). Each such group has an associated label
+ (string), which is shown to the user. To define groups of option
+ boxes, return a list of BoxGroup namedtuples with the label, the key
+ (or index) of the first and last options boxes (inclusive).
+
+ Example:
+ from proto.tools.GeneralGuiTool import BoxGroup
+ return [BoxGroup(label='A group of choices', first='firstKey',
+ last='secondKey')]
+
+ Optional method. Default return value if method is not defined: None
+ """
+ if choices.checkBox:
+ from proto.tools.GeneralGuiTool import BoxGroup
+ return [BoxGroup(label='Extra fields',
+ first='selectionBox',
+ last='textAreaReadonly')]
+
+ @classmethod
+ def getOptionsBoxPasswordField(cls): # Alt: getOptionsBox1()
+ """
+ Defines the type and contents of the input box. User selections are
+ returned to the tools in the prevChoices and choices attributes to
+ other methods. These are lists of results, one for each input box
+ (in the order specified by getInputBoxOrder()).
+
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
+ The input box is defined according to the following syntax:
+
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
+ - Returns: string
+
+ Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
+ - Tuple syntax: (contents, height (#lines) = 1, read only flag = False)
+ - The contents is the default value shown inside the text area
+ - Returns: string
+
+ Raw HTML code: '__rawstr__', 'HTML code'
+ - This is mainly intended for read only usage. Even though more
+ advanced hacks are possible, it is discouraged.
+
+ Password field: '__password__'
+ - Returns: string
+
+ Genome selection box: '__genome__'
+ - Returns: string
+
+ History selection box: ('__history__',) |
+ ('__history__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
+
+ History check box list: ('__multihistory__', ) |
+ ('__multihistory__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
+
+ Hidden field: ('__hidden__', 'Hidden value')
+ - Returns: string
+
+ Table: [['header1','header2'], ['cell1_1','cell1_2'],
+ ['cell2_1','cell2_2']]
+ - Returns: None
+
+ Check box list: OrderedDict([('key1', True), ('key2', False),
+ ('key3', False)])
+ - Returns: OrderedDict from key to selection status (bool).
+
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
+ return '__password__'
+
+ @classmethod
+ def getOptionsBoxRawHtmlWaitForPassword(cls, prevChoices): # Alt: getOptionsBox2()
+ """
+ See getOptionsBoxFirstKey().
+
+ prevChoices is a namedtuple of selections made by the user in the
+ previous input boxes (that is, a namedtuple containing only one element
+ in this case). The elements can accessed either by index, e.g.
+ prevChoices[0] for the result of input box 1, or by key, e.g.
+ prevChoices.key (case 2).
+
+ Mandatory for the subsequent keys (after the first key) defined in
+ getInputBoxNames(), if any.
+ """
+ if prevChoices.passwordField:
+ core = HtmlCore()
+ core.descriptionLine('Password written', prevChoices.passwordField)
+ return '__rawstr__', str(core)
+
+ @classmethod
+ def getOptionsBoxHistorySelectionTabular(cls, prevChoices):
+ return '__history__', 'tabular'
+
+ @classmethod
+ def getOptionsBoxHistoryContents(cls, prevChoices):
+ try:
+ if prevChoices.historySelectionTabular:
+ from proto.CommonFunctions import extractFnFromDatasetInfo
+ fileName = extractFnFromDatasetInfo(prevChoices.historySelectionTabular)
+ with open(fileName) as inputFile:
+ output = ''
+ for i in xrange(10):
+ output += inputFile.readline()
+ return output, 10, True
+ else:
+ return '', 10, True
+ except Exception, e:
+ pass
+ return str(e)
+
+ @classmethod
+ def getOptionsBoxCheckBox(cls, prevChoices):
+ return False
+
+ @classmethod
+ def getOptionsBoxSelectionBox(cls, prevChoices):
+ if prevChoices.checkBox:
+ return [A, B, C]
+
+ @classmethod
+ def getOptionsBoxTextAreaReadWrite(cls, prevChoices):
+ return prevChoices.selectionBox
+
+ @classmethod
+ def getOptionsBoxTextAreaReadonly(cls, prevChoices):
+ return prevChoices.textAreaReadWrite, 1, True
+
+ @classmethod
+ def getOptionsBoxTable(cls, prevChoices):
+ return [['Key', 'Value'],
+ ['selectionBox', prevChoices.selectionBox],
+ ['textAreaReadWrite', prevChoices.textAreaReadWrite],
+ ['passwordField', prevChoices.passwordField]]
+
+ @classmethod
+ def getOptionsBoxCheckBoxList(cls, prevChoices):
+ return OrderedDict([
+ (str(prevChoices.checkBox), False),
+ (str(prevChoices.selectionBox), False),
+ (str(prevChoices.textAreaReadWrite), True),
+ (str(prevChoices.passwordField), False),
+ ])
+
+ @classmethod
+ def getOptionsBoxHidden(cls, prevChoices):
+ return '__hidden__', \
+ '|'.join([key for key, sel in prevChoices.checkBoxList.iteritems() if sel])
+
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
+ # """
+ # If not None, defines the string content of an clickable info box
+ # beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getDemoSelections(cls):
+ # """
+ # Defines a set of demo inputs to the option boxes in the
+ # order defined by getOptionBoxNames and getOptionsBoxOrder.
+ # If not None, a Demo button appears in the interface. Clicking the
+ # button fills the option boxed with the defined demo values.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return ['testChoice1', '..']
+ #
+ # @classmethod
+ # def getExtraHistElements(cls, choices):
+ # """
+ # Defines extra history elements to be created when clicking execute.
+ # This is defined by a list of HistElement objects, as in the
+ # following example:
+ #
+ # from proto.tools.GeneralGuiTool import HistElement
+ # return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
+ #
+ # It is good practice to use class constants for longer strings.
+ #
+ # In the execute() method, one typically needs to fetch the path to
+ # the dataset referred to by the extra history element. To fetch the
+ # path, use the dict cls.extraGalaxyFn with the defined history title
+ # as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def execute(cls, choices, galaxyFn=None, username=''):
+ """
+ Is called when execute-button is pushed by web-user. Should print
+ output as HTML to standard out, which will be directed to a results
+ page in Galaxy history. If getOutputFormat is anything else than
+ 'html', the output should be written to the file with path galaxyFn.
+ If needed, StaticFile can be used to get a path where additional
+ files can be put (cls, e.g. generated image files). choices is a list
+ of selections made by web-user in each options box.
+
+ Mandatory unless isRedirectTool() returns True.
+ """
+ print 'Executing...'
+
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ core = HtmlCore()
+ core.smallHeader('GUI selections (value of prevChoices/choices attributes)')
+ for guiElement in ALL_GUI_ELEMENTS:
+ core.descriptionLine(guiElement[0] + ' [' + guiElement[1] + ']',
+ repr(getattr(choices, guiElement[1])))
+ return str(core)
+
+ # @classmethod
+ # def getSubToolClasses(cls):
+ # """
+ # Specifies a list of classes for subtools of the main tool. These
+ # subtools will be selectable from a selection box at the top of the
+ # page. The input boxes will change according to which subtool is
+ # selected.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ # @classmethod
+ # def isRedirectTool(cls):
+ # """
+ # Specifies whether the tool should redirect to an URL when the Execute
+ # button is clicked.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getRedirectURL(cls, choices):
+ # """
+ # This method is called to return an URL if the isRedirectTool method
+ # returns True.
+ #
+ # Mandatory method if isRedirectTool() returns True.
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def isHistoryTool(cls):
+ # """
+ # Specifies if a History item should be created when the Execute button
+ # is clicked.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def isDynamic(cls):
+ # """
+ # Specifies whether changing the content of textboxes causes the page
+ # to reload. Returning False stops the need for reloading the tool
+ # after each input, resulting in less lags for the user.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ @classmethod
+ def getResetBoxes(cls):
+ """
+ Specifies a list of input boxes which resets the subsequent stored
+ choices previously made. The input boxes are specified by index
+ (starting with 1) or by key.
+
+ Optional method. Default return value if method is not defined: True
+ """
+ return ['selectionBox']
+ #
+ # @classmethod
+ # def getToolDescription(cls):
+ # """
+ # Specifies a help text in HTML that is displayed below the tool.
+ #
+ # Optional method. Default return value if method is not defined: ''
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def getToolIllustration(cls):
+ # """
+ # Specifies an id used by StaticFile.py to reference an illustration
+ # file on disk. The id is a list of optional directory names followed
+ # by a filename. The base directory is STATIC_PATH as defined by
+ # Config.py. The full path is created from the base directory
+ # followed by the id.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getFullExampleURL(cls):
+ # """
+ # Specifies an URL to an example page that describes the tool, for
+ # instance a Galaxy page.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def isDebugMode(cls):
+ # """
+ # Specifies whether the debug mode is turned on. Debug mode is
+ # currently mostly used within the Genomic HyperBrowser and will make
+ # little difference in a plain Galaxy ProTo installation.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getOutputFormat(cls, choices):
+ # """
+ # The format of the history element with the output of the tool. Note
+ # that if 'html' is returned, any print statements in the execute()
+ # method is printed to the output dataset. For text-based output
+ # (e.g. bed) the output dataset only contains text written to the
+ # galaxyFn file, while all print statements are redirected to the info
+ # field of the history item box.
+ #
+ # Note that for 'html' output, standard HTML header and footer code is
+ # added to the output dataset. If one wants to write the complete HTML
+ # page, use the restricted output format 'customhtml' instead.
+ #
+ # Optional method. Default return value if method is not defined:
+ # 'html'
+ # """
+ # return 'html'
+ #
+ # @classmethod
+ # def getOutputName(cls, choices=None):
+ # """
+ # The title (name) of the main output history element.
+ #
+ # Optional method. Default return value if method is not defined:
+ # the name of the tool.
+ # """
+ # return cls.getToolSelectionName()
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool2.xml b/lib/proto/tools/guitest/ProtoGuiTestTool2.xml
new file mode 100644
index 000000000000..4ad881f1e800
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool2.xml
@@ -0,0 +1,4 @@
+
+ Test tool #2 for Galaxy ProTo GUI
+
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool3.py b/lib/proto/tools/guitest/ProtoGuiTestTool3.py
new file mode 100644
index 000000000000..4236a2f3161f
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool3.py
@@ -0,0 +1,508 @@
+import os
+
+import shutil
+
+from proto.CommonFunctions import extractNameFromDatasetInfo, extractFnFromDatasetInfo, \
+ extractFileSuffixFromDatasetInfo, getLoadToGalaxyHistoryURL, getFileSuffix, stripFileSuffix
+from proto.HtmlCore import HtmlCore
+from proto.tools.GeneralGuiTool import GeneralGuiTool
+
+
+class ProtoGuiTestTool3(GeneralGuiTool):
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Inputs and outputs: Test tool #3 for Galaxy ProTo GUI"
+
+ @classmethod
+ def getInputBoxNames(cls):
+ """
+ Specifies a list of headers for the input boxes, and implicitly also
+ the number of input boxes to display on the page. The returned list
+ can have two syntaxes:
+
+ 1) A list of strings denoting the headers for the input boxes in
+ numerical order.
+ 2) A list of tuples of strings, where each tuple has
+ two items: a header and a key.
+
+ The contents of each input box must be defined by the function
+ getOptionsBoxK, where K is either a number in the range of 1 to the
+ number of boxes (case 1), or the specified key (case 2).
+
+ Note: the key has to be camelCase and start with a non-capital letter
+ (e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
+ """
+ return [('Select input histories', 'histories')]
+
+ # @classmethod
+ # def getInputBoxOrder(cls):
+ # """
+ # Specifies the order in which the input boxes should be displayed,
+ # as a list. The input boxes are specified by index (starting with 1)
+ # or by key. If None, the order of the input boxes is in the order
+ # specified by getInputBoxNames().
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getInputBoxGroups(cls, choices=None):
+ # """
+ # Creates a visual separation of groups of consecutive option boxes
+ # from the rest (fieldset). Each such group has an associated label
+ # (string), which is shown to the user. To define groups of option
+ # boxes, return a list of BoxGroup namedtuples with the label, the key
+ # (or index) of the first and last options boxes (inclusive).
+ #
+ # Example:
+ # from proto.tools.GeneralGuiTool import BoxGroup
+ # return [BoxGroup(label='A group of choices', first='firstKey',
+ # last='secondKey')]
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def getOptionsBoxHistories(cls): # Alt: getOptionsBox1()
+ """
+ Defines the type and contents of the input box. User selections are
+ returned to the tools in the prevChoices and choices attributes to
+ other methods. These are lists of results, one for each input box
+ (in the order specified by getInputBoxOrder()).
+
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
+ The input box is defined according to the following syntax:
+
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
+ - Returns: string
+
+ Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
+ - Tuple syntax: (contents, height (#lines) = 1, read only flag = False)
+ - The contents is the default value shown inside the text area
+ - Returns: string
+
+ Raw HTML code: '__rawstr__', 'HTML code'
+ - This is mainly intended for read only usage. Even though more
+ advanced hacks are possible, it is discouraged.
+
+ Password field: '__password__'
+ - Returns: string
+
+ Genome selection box: '__genome__'
+ - Returns: string
+
+ History selection box: ('__history__',) |
+ ('__history__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
+
+ History check box list: ('__multihistory__', ) |
+ ('__multihistory__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
+
+ Hidden field: ('__hidden__', 'Hidden value')
+ - Returns: string
+
+ Table: [['header1','header2'], ['cell1_1','cell1_2'],
+ ['cell2_1','cell2_2']]
+ - Returns: None
+
+ Check box list: OrderedDict([('key1', True), ('key2', False),
+ ('key3', False)])
+ - Returns: OrderedDict from key to selection status (bool).
+
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
+ return '__multihistory__',
+
+ # @classmethod
+ # def getOptionsBoxSecondKey(cls, prevChoices): # Alt: getOptionsBox2()
+ # """
+ # See getOptionsBoxFirstKey().
+ #
+ # prevChoices is a namedtuple of selections made by the user in the
+ # previous input boxes (that is, a namedtuple containing only one element
+ # in this case). The elements can accessed either by index, e.g.
+ # prevChoices[0] for the result of input box 1, or by key, e.g.
+ # prevChoices.key (case 2).
+ #
+ # Mandatory for the subsequent keys (after the first key) defined in
+ # getInputBoxNames(), if any.
+ # """
+ # return ''
+
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
+ # """
+ # If not None, defines the string content of an clickable info box
+ # beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getDemoSelections(cls):
+ # """
+ # Defines a set of demo inputs to the option boxes in the
+ # order defined by getOptionBoxNames and getOptionsBoxOrder.
+ # If not None, a Demo button appears in the interface. Clicking the
+ # button fills the option boxed with the defined demo values.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return ['testChoice1', '..']
+ #
+ @classmethod
+ def getExtraHistElements(cls, choices):
+ """
+ Defines extra history elements to be created when clicking execute.
+ This is defined by a list of HistElement objects, as in the
+ following example:
+
+ from proto.tools.GeneralGuiTool import HistElement
+ return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
+
+ It is good practice to use class constants for longer strings.
+
+ In the execute() method, one typically needs to fetch the path to
+ the dataset referred to by the extra history element. To fetch the
+ path, use the dict cls.extraGalaxyFn with the defined history title
+ as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+
+ Optional method. Default return value if method is not defined: None
+ """
+ if cls._anyHistoriesSelected(choices):
+ from proto.tools.GeneralGuiTool import HistElement
+ return [HistElement(name=name,
+ format='customhtml',
+ label=cls._createHistLabel(name)) for name in
+ cls._getNamesForSelectedHistories(choices)[1:]]
+
+ @classmethod
+ def execute(cls, choices, galaxyFn=None, username=''):
+ """
+ Is called when execute-button is pushed by web-user. Should print
+ output as HTML to standard out, which will be directed to a results
+ page in Galaxy history. If getOutputFormat is anything else than
+ 'html', the output should be written to the file with path galaxyFn.
+ If needed, StaticFile can be used to get a path where additional
+ files can be put (cls, e.g. generated image files). choices is a list
+ of selections made by web-user in each options box.
+
+ Mandatory unless isRedirectTool() returns True.
+ """
+ for i, datasetInfo in enumerate(cls._getDatasetInfoForSelectedHistories(choices)):
+ inFileName, outFileName = cls._getInputAndOutputFileNames(i, datasetInfo, galaxyFn)
+ embeddedFile = cls._createEmbeddedFile(datasetInfo, inFileName, outFileName)
+ htmlContent = cls._generateHtmlContent(datasetInfo, embeddedFile, inFileName)
+ cls._writeHtmlContent(htmlContent, outFileName)
+
+ @classmethod
+ def _getInputAndOutputFileNames(cls, i, datasetInfo, galaxyFn):
+ if i == 0:
+ outFileName = galaxyFn
+ else:
+ datasetName = extractNameFromDatasetInfo(datasetInfo)
+ outFileName = cls.extraGalaxyFn[datasetName]
+
+ inFileName = extractFnFromDatasetInfo(datasetInfo)
+
+ return inFileName, outFileName
+
+ @classmethod
+ def _createEmbeddedFile(cls, datasetInfo, inFileName, outFileName):
+ from proto.StaticFile import GalaxyRunSpecificFile
+
+ inFileSuffix = extractFileSuffixFromDatasetInfo(datasetInfo)
+ inDatasetName = extractNameFromDatasetInfo(datasetInfo)
+ if not inDatasetName.endswith('.' + inFileSuffix):
+ inDatasetName = '.'.join([inDatasetName, inFileSuffix])
+
+ embeddedBaseFileName = cls._cleanUpName(inDatasetName)
+
+ embeddedFile = GalaxyRunSpecificFile(['embedded', embeddedBaseFileName], outFileName)
+ shutil.copy(inFileName, embeddedFile.getDiskPath(ensurePath=True))
+
+ return embeddedFile
+
+ @classmethod
+ def _generateHtmlContent(cls, datasetInfo, embeddedFile, inFileName):
+ with open(inFileName) as inFile:
+ import cgi
+
+ core = HtmlCore()
+ core.begin()
+
+ core.header('File contents')
+ core.fieldsetBegin('Ten first lines of file: ' +
+ extractNameFromDatasetInfo(datasetInfo))
+ core.preformatted(''.join([cgi.escape(inFile.readline()).decode('utf-8', 'ignore')
+ for _ in range(10)]))
+ core.fieldsetEnd()
+
+ core.header('Direct URL to file')
+ embeddedBaseFileName = embeddedFile.getId()[-1]
+ core.paragraph(embeddedFile.getLink(embeddedBaseFileName))
+
+ core.header('Open file in Galaxy history')
+ embeddedFileSuffix = getFileSuffix(embeddedBaseFileName)
+ core.paragraph(embeddedFile.getLoadToHistoryLink
+ (embeddedBaseFileName, galaxyDataType=embeddedFileSuffix))
+
+ core.end()
+
+ return unicode(core)
+
+ @classmethod
+ def _writeHtmlContent(cls, htmlContent, outFileName):
+ import io
+ with io.open(outFileName, 'w', encoding='utf-8') as outFile:
+ outFile.write(htmlContent)
+
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ if not cls._anyHistoriesSelected(choices):
+ return "Please select at least one history element"
+
+ # @classmethod
+ # def getSubToolClasses(cls):
+ # """
+ # Specifies a list of classes for subtools of the main tool. These
+ # subtools will be selectable from a selection box at the top of the
+ # page. The input boxes will change according to which subtool is
+ # selected.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ # @classmethod
+ # def isRedirectTool(cls):
+ # """
+ # Specifies whether the tool should redirect to an URL when the Execute
+ # button is clicked.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getRedirectURL(cls, choices):
+ # """
+ # This method is called to return an URL if the isRedirectTool method
+ # returns True.
+ #
+ # Mandatory method if isRedirectTool() returns True.
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def isHistoryTool(cls):
+ # """
+ # Specifies if a History item should be created when the Execute button
+ # is clicked.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def isDynamic(cls):
+ # """
+ # Specifies whether changing the content of textboxes causes the page
+ # to reload. Returning False stops the need for reloading the tool
+ # after each input, resulting in less lags for the user.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def getResetBoxes(cls):
+ # """
+ # Specifies a list of input boxes which resets the subsequent stored
+ # choices previously made. The input boxes are specified by index
+ # (starting with 1) or by key.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return []
+
+ @classmethod
+ def getToolDescription(cls):
+ """
+ Specifies a help text in HTML that is displayed below the tool.
+
+ Optional method. Default return value if method is not defined: ''
+ """
+ core = HtmlCore()
+ core.paragraph('This test tool creates one output history element for each input '
+ 'history element. The output element is a HTML page showing the first '
+ '10 lines of the corresponding file, as well as a link to the '
+ 'embedded full file. The embedded file are stored together with the '
+ 'history element on disk and is a copy of the original.')
+ core.paragraph('Below is an example of a tool illustration.')
+ core.paragraph('The example link at the bottom currently points to the Galaxy ProTo '
+ 'GitHub page. It would typically point to a Galaxy example page, but does '
+ 'not do so in this case, as Galaxy Pages currently are installation '
+ 'dependent and cannot be distributed with the source code.')
+ return str(core)
+
+ @classmethod
+ def getToolIllustration(cls):
+ """
+ Specifies an id used by StaticFile.py to reference an illustration
+ file on disk. The id is a list of optional directory names followed
+ by a filename. The base directory is STATIC_PATH as defined by
+ Config.py. The full path is created from the base directory
+ followed by the id.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ return ['logo', 'ELIXIR_NORWAY_logo_transparent.png']
+
+ @classmethod
+ def getFullExampleURL(cls):
+ """
+ Specifies an URL to an example page that describes the tool, for
+ instance a Galaxy page.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ return "https://github.com/elixir-no-nels/proto"
+
+ # @classmethod
+ # def isDebugMode(cls):
+ # """
+ # Specifies whether the debug mode is turned on. Debug mode is
+ # currently mostly used within the Genomic HyperBrowser and will make
+ # little difference in a plain Galaxy ProTo installation.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+
+ @classmethod
+ def getOutputFormat(cls, choices):
+ """
+ The format of the history element with the output of the tool. Note
+ that if 'html' is returned, any print statements in the execute()
+ method is printed to the output dataset. For text-based output
+ (e.g. bed) the output dataset only contains text written to the
+ galaxyFn file, while all print statements are redirected to the info
+ field of the history item box.
+
+ Note that for 'html' output, standard HTML header and footer code is
+ added to the output dataset. If one wants to write the complete HTML
+ page, use the restricted output format 'customhtml' instead.
+
+ Optional method. Default return value if method is not defined:
+ 'html'
+ """
+ return 'customhtml'
+
+ @classmethod
+ def getOutputName(cls, choices=None):
+ """
+ The title (name) of the main output history element.
+
+ Optional method. Default return value if method is not defined:
+ the name of the tool.
+ """
+ if cls._anyHistoriesSelected(choices):
+ historyName = cls._getNamesForSelectedHistories(choices)[0]
+ return cls._createHistLabel(historyName)
+
+ @classmethod
+ def _anyHistoriesSelected(cls, choices):
+ return any(sel for sel in choices.histories.values())
+
+ @classmethod
+ def _getNamesForSelectedHistories(cls, choices):
+ return [extractNameFromDatasetInfo(datasetInfo) for datasetInfo in
+ cls._getDatasetInfoForSelectedHistories(choices)]
+
+ @classmethod
+ def _getDatasetInfoForSelectedHistories(cls, choices):
+ return [val for val in choices.histories.values() if val]
+
+ @classmethod
+ def _cleanUpName(cls, historyName):
+ histNum, histLabel = historyName.split(' - ', 1)
+ return '_'.join([histNum] + histLabel.lower().split(' '))
+
+ @classmethod
+ def _createHistLabel(cls, name):
+ cleanupName = cls._cleanUpName(name)
+ return 'Embedded file: ' + cleanupName
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool3.xml b/lib/proto/tools/guitest/ProtoGuiTestTool3.xml
new file mode 100644
index 000000000000..4ca21f746f71
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool3.xml
@@ -0,0 +1,4 @@
+
+ Test tool #3 for Galaxy ProTo GUI
+
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool4.py b/lib/proto/tools/guitest/ProtoGuiTestTool4.py
new file mode 100644
index 000000000000..890f12f4f99f
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool4.py
@@ -0,0 +1,47 @@
+from proto.tools.GeneralGuiTool import MultiGeneralGuiTool
+
+
+class ProtoGuiTestTool4(MultiGeneralGuiTool):
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Multitool: Test tool #4 for Galaxy ProTo GUI"
+
+ @staticmethod
+ def getToolSelectionName():
+ return "----- Select ProTo GUI test tool -----"
+
+ @staticmethod
+ def getSubToolSelectionTitle():
+ return 'Select ProTo GUI test #4 subtool:'
+
+ @classmethod
+ def getSubToolClasses(cls):
+ """
+ Specifies a list of classes for subtools of the main tool. These
+ subtools will be selectable from a selection box at the top of the
+ page. The input boxes will change according to which subtool is
+ selected.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ from proto.tools.guitest.ProtoGuiTestTool1 import ProtoGuiTestTool1
+ from proto.tools.guitest.ProtoGuiTestTool2 import ProtoGuiTestTool2
+ from proto.tools.guitest.ProtoGuiTestTool3 import ProtoGuiTestTool3
+ return [ProtoGuiTestTool1, ProtoGuiTestTool2, ProtoGuiTestTool3]
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool4.xml b/lib/proto/tools/guitest/ProtoGuiTestTool4.xml
new file mode 100644
index 000000000000..d127394eaec4
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool4.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool5.py b/lib/proto/tools/guitest/ProtoGuiTestTool5.py
new file mode 100644
index 000000000000..cc1308aac37d
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool5.py
@@ -0,0 +1,426 @@
+from proto.tools.GeneralGuiTool import GeneralGuiTool
+
+
+class ProtoGuiTestTool5(GeneralGuiTool):
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Redirect tool (square matrix): Test tool #5 for Galaxy ProTo GUI"
+
+ @classmethod
+ def getInputBoxNames(cls):
+ """
+ Specifies a list of headers for the input boxes, and implicitly also
+ the number of input boxes to display on the page. The returned list
+ can have two syntaxes:
+
+ 1) A list of strings denoting the headers for the input boxes in
+ numerical order.
+ 2) A list of tuples of strings, where each tuple has
+ two items: a header and a key.
+
+ The contents of each input box must be defined by the function
+ getOptionsBoxK, where K is either a number in the range of 1 to the
+ number of boxes (case 1), or the specified key (case 2).
+
+ Note: the key has to be camelCase and start with a non-capital letter
+ (e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
+ """
+ return [('Select number of rows/cols (equal)', 'numRowCols')]
+
+ # @classmethod
+ # def getInputBoxOrder(cls):
+ # """
+ # Specifies the order in which the input boxes should be displayed,
+ # as a list. The input boxes are specified by index (starting with 1)
+ # or by key. If None, the order of the input boxes is in the order
+ # specified by getInputBoxNames().
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getInputBoxGroups(cls, choices=None):
+ # """
+ # Creates a visual separation of groups of consecutive option boxes
+ # from the rest (fieldset). Each such group has an associated label
+ # (string), which is shown to the user. To define groups of option
+ # boxes, return a list of BoxGroup namedtuples with the label, the key
+ # (or index) of the first and last options boxes (inclusive).
+ #
+ # Example:
+ # from proto.tools.GeneralGuiTool import BoxGroup
+ # return [BoxGroup(label='A group of choices', first='firstKey',
+ # last='secondKey')]
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ @classmethod
+ def getOptionsBoxNumRowCols(cls): # Alt: getOptionsBox1()
+ """
+ Defines the type and contents of the input box. User selections are
+ returned to the tools in the prevChoices and choices attributes to
+ other methods. These are lists of results, one for each input box
+ (in the order specified by getInputBoxOrder()).
+
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
+ The input box is defined according to the following syntax:
+
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
+ - Returns: string
+
+ Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
+ - Tuple syntax: (contents, height (#lines) = 1, read only flag = False)
+ - The contents is the default value shown inside the text area
+ - Returns: string
+
+ Raw HTML code: '__rawstr__', 'HTML code'
+ - This is mainly intended for read only usage. Even though more
+ advanced hacks are possible, it is discouraged.
+
+ Password field: '__password__'
+ - Returns: string
+
+ Genome selection box: '__genome__'
+ - Returns: string
+
+ History selection box: ('__history__',) |
+ ('__history__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
+
+ History check box list: ('__multihistory__', ) |
+ ('__multihistory__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
+
+ Hidden field: ('__hidden__', 'Hidden value')
+ - Returns: string
+
+ Table: [['header1','header2'], ['cell1_1','cell1_2'],
+ ['cell2_1','cell2_2']]
+ - Returns: None
+
+ Check box list: OrderedDict([('key1', True), ('key2', False),
+ ('key3', False)])
+ - Returns: OrderedDict from key to selection status (bool).
+
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
+ return '2'
+
+ # @classmethod
+ # def getOptionsBoxSecondKey(cls, prevChoices): # Alt: getOptionsBox2()
+ # """
+ # See getOptionsBoxFirstKey().
+ #
+ # prevChoices is a namedtuple of selections made by the user in the
+ # previous input boxes (that is, a namedtuple containing only one element
+ # in this case). The elements can accessed either by index, e.g.
+ # prevChoices[0] for the result of input box 1, or by key, e.g.
+ # prevChoices.key (case 2).
+ #
+ # Mandatory for the subsequent keys (after the first key) defined in
+ # getInputBoxNames(), if any.
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
+ # """
+ # If not None, defines the string content of an clickable info box
+ # beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getDemoSelections(cls):
+ # """
+ # Defines a set of demo inputs to the option boxes in the
+ # order defined by getOptionBoxNames and getOptionsBoxOrder.
+ # If not None, a Demo button appears in the interface. Clicking the
+ # button fills the option boxed with the defined demo values.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return ['testChoice1', '..']
+ #
+ # @classmethod
+ # def getExtraHistElements(cls, choices):
+ # """
+ # Defines extra history elements to be created when clicking execute.
+ # This is defined by a list of HistElement objects, as in the
+ # following example:
+ #
+ # from proto.tools.GeneralGuiTool import HistElement
+ # return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
+ #
+ # It is good practice to use class constants for longer strings.
+ #
+ # In the execute() method, one typically needs to fetch the path to
+ # the dataset referred to by the extra history element. To fetch the
+ # path, use the dict cls.extraGalaxyFn with the defined history title
+ # as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def execute(cls, choices, galaxyFn=None, username=''):
+ # """
+ # Is called when execute-button is pushed by web-user. Should print
+ # output as HTML to standard out, which will be directed to a results
+ # page in Galaxy history. If getOutputFormat is anything else than
+ # 'html', the output should be written to the file with path galaxyFn.
+ # If needed, StaticFile can be used to get a path where additional
+ # files can be put (cls, e.g. generated image files). choices is a list
+ # of selections made by web-user in each options box.
+ #
+ # Mandatory unless isRedirectTool() returns True.
+ # """
+ # print 'Executing...'
+
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ return No
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ if not choices.numRowCols:
+ return 'Please enter the number of rows/cols of the new square matrix.'
+
+ try:
+ numRowCols = int(choices.numRowCols)
+ except:
+ return 'Please enter an integer'
+
+ from proto.tools.guitest.ProtoGuiTestTool6 import ProtoGuiTestTool6
+ if numRowCols < 2 or numRowCols > ProtoGuiTestTool6.MAX_ROWS_AND_COLS:
+ return 'Number of rows and cols must be in the interval [2, {}].'.format(
+ ProtoGuiTestTool6.MAX_ROWS_AND_COLS
+ )
+
+ # @classmethod
+ # def getSubToolClasses(cls):
+ # """
+ # Specifies a list of classes for subtools of the main tool. These
+ # subtools will be selectable from a selection box at the top of the
+ # page. The input boxes will change according to which subtool is
+ # selected.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return False
+
+ @classmethod
+ def isRedirectTool(cls):
+ """
+ Specifies whether the tool should redirect to an URL when the Execute
+ button is clicked.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ @classmethod
+ def getRedirectURL(cls, choices):
+ """
+ This method is called to return an URL if the isRedirectTool method
+ returns True.
+
+ Mandatory method if isRedirectTool() returns True.
+ """
+ from proto.CommonFunctions import createToolURL
+ return createToolURL('proto_proto_gui_test_tool6',
+ numRows=choices.numRowCols,
+ numCols=choices.numRowCols)
+
+ # @classmethod
+ # def isHistoryTool(cls):
+ # """
+ # Specifies if a History item should be created when the Execute button
+ # is clicked.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def isDynamic(cls):
+ # """
+ # Specifies whether changing the content of textboxes causes the page
+ # to reload. Returning False stops the need for reloading the tool
+ # after each input, resulting in less lags for the user.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def getResetBoxes(cls):
+ # """
+ # Specifies a list of input boxes which resets the subsequent stored
+ # choices previously made. The input boxes are specified by index
+ # (starting with 1) or by key.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return []
+
+ @classmethod
+ def getToolDescription(cls):
+ """
+ Specifies a help text in HTML that is displayed below the tool.
+
+ Optional method. Default return value if method is not defined: ''
+ """
+ from proto.HtmlCore import HtmlCore
+ core = HtmlCore()
+ core.paragraph('Not publicly available, in order to test the "isPublic()" method.')
+ core.paragraph('There should also be an error message for incorrect illustration ' \
+ 'path, testing "getDebugMode()".')
+ return unicode(core)
+
+ @classmethod
+ def getToolIllustration(cls):
+ """
+ Specifies an id used by StaticFile.py to reference an illustration
+ file on disk. The id is a list of optional directory names followed
+ by a filename. The base directory is STATIC_PATH as defined by
+ Config.py. The full path is created from the base directory
+ followed by the id.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ return ['doesnotexist.png']
+
+ # @classmethod
+ # def getFullExampleURL(cls):
+ # """
+ # Specifies an URL to an example page that describes the tool, for
+ # instance a Galaxy page.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isDebugMode(cls):
+ """
+ Specifies whether the debug mode is turned on. Debug mode is
+ currently mostly used within the Genomic HyperBrowser and will make
+ little difference in a plain Galaxy ProTo installation.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ # @classmethod
+ # def getOutputFormat(cls, choices):
+ # """
+ # The format of the history element with the output of the tool. Note
+ # that if 'html' is returned, any print statements in the execute()
+ # method is printed to the output dataset. For text-based output
+ # (e.g. bed) the output dataset only contains text written to the
+ # galaxyFn file, while all print statements are redirected to the info
+ # field of the history item box.
+ #
+ # Note that for 'html' output, standard HTML header and footer code is
+ # added to the output dataset. If one wants to write the complete HTML
+ # page, use the restricted output format 'customhtml' instead.
+ #
+ # Optional method. Default return value if method is not defined:
+ # 'html'
+ # """
+ # return 'html'
+ #
+ # @classmethod
+ # def getOutputName(cls, choices=None):
+ # """
+ # The title (name) of the main output history element.
+ #
+ # Optional method. Default return value if method is not defined:
+ # the name of the tool.
+ # """
+ # return cls.getToolSelectionName()
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool5.xml b/lib/proto/tools/guitest/ProtoGuiTestTool5.xml
new file mode 100644
index 000000000000..c798ec9660f3
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool5.xml
@@ -0,0 +1,4 @@
+
+ Test tool #5 for Galaxy ProTo GUI
+
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool6.py b/lib/proto/tools/guitest/ProtoGuiTestTool6.py
new file mode 100644
index 000000000000..01fc5eacc0f3
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool6.py
@@ -0,0 +1,514 @@
+from proto.HtmlCore import HtmlCore
+from proto.tools.GeneralGuiTool import GeneralGuiTool
+
+
+class ProtoGuiTestTool6(GeneralGuiTool):
+ MAX_ROWS_AND_COLS = 5
+ SELECT_R_OPERATION = '-- No selection (or finished selecting) --'
+ CLEAR_OPERATION_QUEUE = '-- Clear matrix operation queue --'
+
+ @classmethod
+ def getToolName(cls):
+ """
+ Specifies a header of the tool, which is displayed at the top of the
+ page.
+
+ Mandatory method for all ProTo tools.
+ """
+ return "Variable number of inputs and R: Test tool #6 for Galaxy ProTo GUI"
+
+ @classmethod
+ def getInputBoxNames(cls):
+ """
+ Specifies a list of headers for the input boxes, and implicitly also
+ the number of input boxes to display on the page. The returned list
+ can have two syntaxes:
+
+ 1) A list of strings denoting the headers for the input boxes in
+ numerical order.
+ 2) A list of tuples of strings, where each tuple has
+ two items: a header and a key.
+
+ The contents of each input box must be defined by the function
+ getOptionsBoxK, where K is either a number in the range of 1 to the
+ number of boxes (case 1), or the specified key (case 2).
+
+ Note: the key has to be camelCase and start with a non-capital letter
+ (e.g. "firstKey")
+
+ Optional method. Default return value if method is not defined: []
+ """
+ return [('Number of rows (2-{})'.format(cls.MAX_ROWS_AND_COLS), 'numRows'),
+ ('Number of columns (2-{})'.format(cls.MAX_ROWS_AND_COLS), 'numCols')] +\
+ [('Value in matrix element ({}, {})'.format(i, j), 'extra{}_{}'.format(i, j))
+ for i in xrange(cls.MAX_ROWS_AND_COLS) for j in xrange(cls.MAX_ROWS_AND_COLS)] +\
+ [('Matrix', 'matrix'),
+ ('Select next R single matrix operation', 'operation'),
+ ('Operation queue', 'queue'),
+ ('Operation queue (Html)', 'queueHtml')]
+
+ # @classmethod
+ # def getInputBoxOrder(cls):
+ # """
+ # Specifies the order in which the input boxes should be displayed,
+ # as a list. The input boxes are specified by index (starting with 1)
+ # or by key. If None, the order of the input boxes is in the order
+ # specified by getInputBoxNames().
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getInputBoxGroups(cls, choices=None):
+ # """
+ # Creates a visual separation of groups of consecutive option boxes
+ # from the rest (fieldset). Each such group has an associated label
+ # (string), which is shown to the user. To define groups of option
+ # boxes, return a list of BoxGroup namedtuples with the label, the key
+ # (or index) of the first and last options boxes (inclusive).
+ #
+ # Example:
+ # from proto.tools.GeneralGuiTool import BoxGroup
+ # return [BoxGroup(label='A group of choices', first='firstKey',
+ # last='secondKey')]
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def getOptionsBoxNumRows(cls): # Alt: getOptionsBox1()
+ """
+ Defines the type and contents of the input box. User selections are
+ returned to the tools in the prevChoices and choices attributes to
+ other methods. These are lists of results, one for each input box
+ (in the order specified by getInputBoxOrder()).
+
+ Mandatory for the first key defined in getInputBoxNames(), if any.
+
+ The input box is defined according to the following syntax:
+
+ Check box: False | True
+ - Returns: bool
+
+ Selection box: ['choice1', 'choice2']
+ - Returns: string
+
+ Text area: 'textbox' | ('textbox',1) | ('textbox',1,False)
+ - Tuple syntax: (contents, height (#lines) = 1, read only flag = False)
+ - The contents is the default value shown inside the text area
+ - Returns: string
+
+ Raw HTML code: '__rawstr__', 'HTML code'
+ - This is mainly intended for read only usage. Even though more
+ advanced hacks are possible, it is discouraged.
+
+ Password field: '__password__'
+ - Returns: string
+
+ Genome selection box: '__genome__'
+ - Returns: string
+
+ History selection box: ('__history__',) |
+ ('__history__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: colon-separated string denoting Galaxy dataset info, as
+ described below.
+
+ History check box list: ('__multihistory__', ) |
+ ('__multihistory__', 'bed', 'wig')
+ - Only history items of specified types are shown.
+ - Returns: OrderedDict with Galaxy dataset ids as key (the number YYYY
+ as described below), and the associated Galaxy dataset info as the
+ values, given that the history element is ticked off by the user.
+ If not, the value is set to None. The Galaxy dataset info structure
+ is described below.
+
+ Hidden field: ('__hidden__', 'Hidden value')
+ - Returns: string
+
+ Table: [['header1','header2'], ['cell1_1','cell1_2'],
+ ['cell2_1','cell2_2']]
+ - Returns: None
+
+ Check box list: OrderedDict([('key1', True), ('key2', False),
+ ('key3', False)])
+ - Returns: OrderedDict from key to selection status (bool).
+
+
+ ###
+ Note about the "Galaxy dataset info" data structure:
+ ###
+
+ "Galaxy dataset info" is a list of strings coding information about a
+ Galaxy history element and its associated dataset, typically used to
+ provide info on the history element selected by the user as input to a
+ ProTo tool.
+
+ Structure:
+ ['galaxy', fileFormat, path, name]
+
+ Optionally encoded as a single string, delineated by colon:
+
+ 'galaxy:fileFormat:path:name'
+
+ Where:
+ 'galaxy' used for assertions in the code
+ fileFormat (or suffix) contains the file format of the dataset, as
+ encoded in the 'format' field of a Galaxy history element.
+ path (or file name/fn) is the disk path to the dataset file.
+ Typically ends with 'XXX/dataset_YYYY.dat'. XXX and YYYY are
+ numbers which are extracted and used as an unique id of the
+ dataset in the form [XXX, YYYY]
+ name is the title of the history element
+
+ The different parts can be extracted using the functions
+ extractFileSuffixFromDatasetInfo(), extractFnFromDatasetInfo(), and
+ extractNameFromDatasetInfo() from the module CommonFunctions.py.
+ """
+ return '2'
+
+ @classmethod
+ def getOptionsBoxNumCols(cls, prevChoices): # Alt: getOptionsBox2()
+ """
+ See getOptionsBoxFirstKey().
+
+ prevChoices is a namedtuple of selections made by the user in the
+ previous input boxes (that is, a namedtuple containing only one element
+ in this case). The elements can accessed either by index, e.g.
+ prevChoices[0] for the result of input box 1, or by key, e.g.
+ prevChoices.key (case 2).
+
+ Mandatory for the subsequent keys (after the first key) defined in
+ getInputBoxNames(), if any.
+ """
+ return '2'
+
+ @classmethod
+ def _getOptionBoxExtra(cls, prevChoices, i, j):
+ if i < int(prevChoices.numRows) and j < int(prevChoices.numCols):
+ return '0'
+
+ @classmethod
+ def setupExtraBoxMethods(cls):
+ from functools import partial
+ for i in xrange(cls.MAX_ROWS_AND_COLS):
+ for j in xrange(cls.MAX_ROWS_AND_COLS):
+ setattr(cls, 'getOptionsBoxExtra{}_{}'.format(i, j),
+ partial(cls._getOptionBoxExtra, i=i, j=j))
+
+ @classmethod
+ def getOptionsBoxMatrix(cls, prevChoices):
+ return cls._getMatrixFromChoices(prevChoices)
+
+ @classmethod
+ def _getMatrixFromChoices(cls, prevChoices):
+ import numpy as np
+ allVals = np.array([float(_) for _ in cls._getExtraChoices(prevChoices)])
+ matrix = allVals.reshape((int(prevChoices.numRows), int(prevChoices.numCols))).tolist()
+ return matrix
+
+ @classmethod
+ def getOptionsBoxOperation(cls, prevChoices):
+ return [cls.SELECT_R_OPERATION, 'crossprod', 't', 'solve', cls.CLEAR_OPERATION_QUEUE]
+
+ @classmethod
+ def getOptionsBoxQueue(cls, prevChoices):
+ queue = prevChoices.queue
+ operation = prevChoices.operation
+
+ if operation == cls.CLEAR_OPERATION_QUEUE:
+ ret = ''
+ elif operation == cls.SELECT_R_OPERATION:
+ ret = queue if queue is not None else ''
+ else:
+ ret = '|'.join([queue, operation]) if queue else operation
+
+ return '__hidden__', ret
+
+ @classmethod
+ def getOptionsBoxQueueHtml(cls, prevChoices):
+ queue = prevChoices.queue
+ core = HtmlCore()
+
+ core.smallHeader('Queue of R single matrix operations')
+ if queue:
+ for i, operation in enumerate(queue.split('|')):
+ core.descriptionLine(str(i + 1), operation)
+ else:
+ core.paragraph('No matrix operations selected.')
+
+ return '__rawstr__', unicode(core)
+
+ # @classmethod
+ # def getInfoForOptionsBoxKey(cls, prevChoices):
+ # """
+ # If not None, defines the string content of an clickable info box
+ # beside the corresponding input box. HTML is allowed.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def getDemoSelections(cls):
+ """
+ Defines a set of demo inputs to the option boxes in the
+ order defined by getOptionBoxNames and getOptionsBoxOrder.
+ If not None, a Demo button appears in the interface. Clicking the
+ button fills the option boxed with the defined demo values.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ return ['2', '2', '3', '4'] +\
+ [''] * (cls.MAX_ROWS_AND_COLS - 2) +\
+ ['1', '2'] +\
+ [''] * (cls.MAX_ROWS_AND_COLS - 2) +\
+ [''] * ((cls.MAX_ROWS_AND_COLS - 2) * cls.MAX_ROWS_AND_COLS) +\
+ ['None', cls.SELECT_R_OPERATION, 'crossprod|solve|t', 'None']
+
+ # @classmethod
+ # def getExtraHistElements(cls, choices):
+ # """
+ # Defines extra history elements to be created when clicking execute.
+ # This is defined by a list of HistElement objects, as in the
+ # following example:
+ #
+ # from proto.tools.GeneralGuiTool import HistElement
+ # return [HistElement(cls.HISTORY_TITLE, 'bed', hidden=False)]
+ #
+ # It is good practice to use class constants for longer strings.
+ #
+ # In the execute() method, one typically needs to fetch the path to
+ # the dataset referred to by the extra history element. To fetch the
+ # path, use the dict cls.extraGalaxyFn with the defined history title
+ # as key, e.g. "cls.extraGalaxyFn[cls.HISTORY_TITLE]".
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def execute(cls, choices, galaxyFn=None, username=''):
+ """
+ Is called when execute-button is pushed by web-user. Should print
+ output as HTML to standard out, which will be directed to a results
+ page in Galaxy history. If getOutputFormat is anything else than
+ 'html', the output should be written to the file with path galaxyFn.
+ If needed, StaticFile can be used to get a path where additional
+ files can be put (cls, e.g. generated image files). choices is a list
+ of selections made by web-user in each options box.
+
+ Mandatory unless isRedirectTool() returns True.
+ """
+ from proto.RSetup import r
+
+ core = HtmlCore()
+
+ try:
+ mat = cls._getMatrixFromChoices(choices)
+ for operation in choices.queue.split('|'):
+ mat = r[operation](mat).tolist()
+ except Exception, e:
+ core.paragraph(str(e))
+ else:
+ core.smallHeader('Output matrix after all R single matrix operations have been '
+ 'carried out:')
+ core.tableHeader([])
+ for rowNum in range(len(mat)):
+ core.tableLine(mat[rowNum])
+ core.tableFooter()
+
+ return unicode(core)
+
+ @classmethod
+ def validateAndReturnErrors(cls, choices):
+ """
+ Should validate the selected input parameters. If the parameters are
+ not valid, an error text explaining the problem should be returned.
+ The GUI then shows this text to the user (if not empty) and greys
+ out the execute button (even if the text is empty). If all
+ parameters are valid, the method should return None, which enables
+ the execute button.
+
+ Optional method. Default return value if method is not defined: None
+ """
+ for optionsBox in ['numRows', 'numCols']:
+ val = getattr(choices, optionsBox)
+ try:
+ num = int(val)
+ if num < 2 or num > cls.MAX_ROWS_AND_COLS:
+ return '"{}" is not in interval [2, {}]: {}'.format(
+ optionsBox, cls.MAX_ROWS_AND_COLS, val)
+ except:
+ return '"{}" is not an integer: {}'.format(optionsBox, val)
+
+ extraChoices = ProtoGuiTestTool6._getExtraChoices(choices)
+ for x, val in enumerate(extraChoices):
+ try:
+ num = float(val)
+ except:
+ numCols = int(choices.numCols)
+ i = x / numCols
+ j = x % numCols
+ return 'Value in matrix element ({}, {}) is not a float: {}'.format(i, j, val)
+
+ if not choices.queue:
+ return 'Please select at least one R matrix operation'
+
+ @classmethod
+ def _getExtraChoices(cls, choices):
+ return [getattr(choices, 'extra{}_{}'.format(i, j)) \
+ for i in xrange(int(choices.numRows))
+ for j in xrange(int(choices.numCols))]
+
+ # @classmethod
+ # def getSubToolClasses(cls):
+ # """
+ # Specifies a list of classes for subtools of the main tool. These
+ # subtools will be selectable from a selection box at the top of the
+ # page. The input boxes will change according to which subtool is
+ # selected.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+
+ @classmethod
+ def isPublic(cls):
+ """
+ Specifies whether the tool is accessible to all users. If False, the
+ tool is only accessible to a restricted set of users as well as admin
+ users, as defined in the galaxy.ini file.
+
+ Optional method. Default return value if method is not defined: False
+ """
+ return True
+
+ # @classmethod
+ # def isRedirectTool(cls):
+ # """
+ # Specifies whether the tool should redirect to an URL when the Execute
+ # button is clicked.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getRedirectURL(cls, choices):
+ # """
+ # This method is called to return an URL if the isRedirectTool method
+ # returns True.
+ #
+ # Mandatory method if isRedirectTool() returns True.
+ # """
+ # return ''
+
+ @classmethod
+ def isHistoryTool(cls):
+ """
+ Specifies if a History item should be created when the Execute button
+ is clicked.
+
+ Optional method. Default return value if method is not defined: True
+ """
+ return False
+
+ # @classmethod
+ # def isDynamic(cls):
+ # """
+ # Specifies whether changing the content of textboxes causes the page
+ # to reload. Returning False stops the need for reloading the tool
+ # after each input, resulting in less lags for the user.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return True
+ #
+ # @classmethod
+ # def getResetBoxes(cls):
+ # """
+ # Specifies a list of input boxes which resets the subsequent stored
+ # choices previously made. The input boxes are specified by index
+ # (starting with 1) or by key.
+ #
+ # Optional method. Default return value if method is not defined: True
+ # """
+ # return []
+ #
+ # @classmethod
+ # def getToolDescription(cls):
+ # """
+ # Specifies a help text in HTML that is displayed below the tool.
+ #
+ # Optional method. Default return value if method is not defined: ''
+ # """
+ # return ''
+ #
+ # @classmethod
+ # def getToolIllustration(cls):
+ # """
+ # Specifies an id used by StaticFile.py to reference an illustration
+ # file on disk. The id is a list of optional directory names followed
+ # by a filename. The base directory is STATIC_PATH as defined by
+ # Config.py. The full path is created from the base directory
+ # followed by the id.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def getFullExampleURL(cls):
+ # """
+ # Specifies an URL to an example page that describes the tool, for
+ # instance a Galaxy page.
+ #
+ # Optional method. Default return value if method is not defined: None
+ # """
+ # return None
+ #
+ # @classmethod
+ # def isDebugMode(cls):
+ # """
+ # Specifies whether the debug mode is turned on. Debug mode is
+ # currently mostly used within the Genomic HyperBrowser and will make
+ # little difference in a plain Galaxy ProTo installation.
+ #
+ # Optional method. Default return value if method is not defined: False
+ # """
+ # return False
+ #
+ # @classmethod
+ # def getOutputFormat(cls, choices):
+ # """
+ # The format of the history element with the output of the tool. Note
+ # that if 'html' is returned, any print statements in the execute()
+ # method is printed to the output dataset. For text-based output
+ # (e.g. bed) the output dataset only contains text written to the
+ # galaxyFn file, while all print statements are redirected to the info
+ # field of the history item box.
+ #
+ # Note that for 'html' output, standard HTML header and footer code is
+ # added to the output dataset. If one wants to write the complete HTML
+ # page, use the restricted output format 'customhtml' instead.
+ #
+ # Optional method. Default return value if method is not defined:
+ # 'html'
+ # """
+ # return 'html'
+ #
+ # @classmethod
+ # def getOutputName(cls, choices=None):
+ # """
+ # The title (name) of the main output history element.
+ #
+ # Optional method. Default return value if method is not defined:
+ # the name of the tool.
+ # """
+ # return cls.getToolSelectionName()
+
+
+ProtoGuiTestTool6.setupExtraBoxMethods()
diff --git a/lib/proto/tools/guitest/ProtoGuiTestTool6.xml b/lib/proto/tools/guitest/ProtoGuiTestTool6.xml
new file mode 100644
index 000000000000..32180bced902
--- /dev/null
+++ b/lib/proto/tools/guitest/ProtoGuiTestTool6.xml
@@ -0,0 +1,4 @@
+
+ Test tool #6 for Galaxy ProTo GUI
+
diff --git a/lib/proto/tools/guitest/__init__.py b/lib/proto/tools/guitest/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/scripts/common_startup.sh b/scripts/common_startup.sh
index a239c4892136..edadaa7cd1e8 100755
--- a/scripts/common_startup.sh
+++ b/scripts/common_startup.sh
@@ -8,10 +8,10 @@ for arg in "$@"; do
[ "$arg" = "--skip-venv" ] && SET_VENV=0
done
-# Conda Python is in use, do not use virtualenv
-if python -V 2>&1 | grep -q 'Continuum Analytics'; then
- SET_VENV=0
-fi
+## Conda Python is in use, do not use virtualenv
+#if python -V 2>&1 | grep -q 'Continuum Analytics'; then
+# SET_VENV=0
+#fi
DEV_WHEELS=0
FETCH_WHEELS=1
@@ -128,7 +128,7 @@ if [ $SET_VENV -eq 1 ]; then
then
printf "Setting up R in virtualenv at $GALAXY_VIRTUAL_ENV\n"
- echo 'export R_LIBS=$VIRTUAL_ENV/R/library' >>$GALAXY_VIRTUAL_ENV/bin/activate
+ printf '\nexport R_LIBS=$VIRTUAL_ENV/R/library' >>$GALAXY_VIRTUAL_ENV/bin/activate
for LIB in $GALAXY_VIRTUAL_ENV/lib/python*
do
echo 'import os,sys; os.environ["R_LIBS"]=sys.prefix+"/R/library"' >$LIB/sitecustomize.py
diff --git a/static/proto/html/ToolTemplate.html b/static/proto/html/ToolTemplate.html
index e1bf627d9799..1ac42602b708 100644
--- a/static/proto/html/ToolTemplate.html
+++ b/static/proto/html/ToolTemplate.html
@@ -90,7 +90,7 @@
(or index) of the first and last options boxes (inclusive).
Example:
- from quick.webtool.GeneralGuiTool import BoxGroup
+ from proto.tools.GeneralGuiTool import BoxGroup
return [BoxGroup(label='A group of choices', first='firstKey',
last='secondKey')]
@@ -130,7 +130,10 @@
The input box is defined according to the following syntax:
"}});return{View:e}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1))},function(t,e,i){var a,n;(function(i,o,s){a=[],n=function(){var t=i.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:!0,id:null,href:null,target:null,enabled:!0,visible:!0,tooltip_config:{}}}),e=i.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"},this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var t=this.template(this.model.toJSON());return t.tooltip(this.model.get("tooltip_config")),this.$el.replaceWith(t),this.setElement(t),this},events:{click:"click"},click:function(t){return!o.isFunction(this.model.get("on_click"))||(this.model.get("on_click")(t),!1)},template:function(t){var e='title="'+t.title+'" class="icon-button';return t.is_menu_button&&(e+=" menu-button"),e+=" "+t.icon_class,t.enabled||(e+="_disabled"),e+='"',t.id&&(e+=' id="'+t.id+'"'),e+=' href="'+t.href+'"',t.target&&(e+=' target="'+t.target+'"'),t.visible||(e+=' style="display: none;"'),e=t.enabled?"":"",s(e)}}),a=i.Collection.extend({model:t}),n=i.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var t=this;return this.collection.each(function(e){var i=s("").attr("href","javascript:void(0)").attr("title",e.attributes.title).addClass("icon-button menu-button").addClass(e.attributes.icon_class).appendTo(t.$el).click(e.attributes.on_click);e.attributes.tooltip_config&&i.tooltip(e.attributes.tooltip_config);var a=e.get("options");a&&make_popupmenu(i,a)}),this}}),r=function(e,i){i||(i={});var s=new a(o.map(e,function(e){return new t(o.extend(e,i))}));return new n({collection:s})};return{IconButton:t,IconButtonView:e,IconButtonCollection:a,IconButtonMenuView:n,create_icon_buttons_menu:r}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(3),i(1))},function(t,e,i){var a,n,o;!function(s){n=[i(1)],a=s,o="function"==typeof a?a.apply(e,n):a,!(void 0!==o&&(t.exports=o))}(function(t){"use_strict";var e=t;e.fn.make_text_editable=function(t){var i="num_cols"in t?t.num_cols:30,a="num_rows"in t?t.num_rows:4,n="use_textarea"in t&&t.use_textarea,o="on_finish"in t?t.on_finish:null,s="help_text"in t?t.help_text:null,r=e(this);return r.addClass("editable-text").click(function(s){if(!(e(this).children(":input").length>0)){r.removeClass("editable-text");var l,c,h=function(t){r.find(":input").remove(),""!==t?r.text(t):r.html(" "),r.addClass("editable-text"),o&&o(t)},d="cur_text"in t?t.cur_text:r.text();n?(l=e("").attr({rows:a,cols:i}).text(e.trim(d)).keyup(function(t){27===t.keyCode&&h(d)}),c=e("").text("Done").click(function(){return h(l.val()),!1})):l=e("").attr({value:e.trim(d),size:i}).blur(function(){h(d)}).keyup(function(t){27===t.keyCode?e(this).trigger("blur"):13===t.keyCode&&h(e(this).val()),t.stopPropagation()}),r.text(""),r.append(l),c&&r.append(c),l.focus(),l.select(),s.stopPropagation()}}),s&&r.attr("title",s).tooltip(),r}})},function(t,e,i){var a;(function(n,o){a=function(){function t(t){t+="";for(var e=/(\d+)(\d{3})/;e.test(t);)t=t.replace(e,"$1,$2");return t}var e=function(t){return"promise"in t},i=n.Model.extend({defaults:{ajax_settings:{},interval:1e3,success_fn:function(t){return!0}},go:function(){var t=o.Deferred(),e=this,i=e.get("ajax_settings"),a=e.get("success_fn"),n=e.get("interval"),s=function(){o.ajax(i).success(function(e){a(e)?t.resolve(e):setTimeout(s,n)})};return s(),t}}),a=function(t){t||(t="#ffffff"),"string"==typeof t&&(t=[t]);for(var e=0;e>16,n=(65280&i)>>8,o=255&i,h=p(a,n,o),f=!0,e=0;e>16,l=(65280&s)>>8,c=255&s,d=p(r,l,c),u=g(a,n,o,r,l,c),Math.abs(h-d)<40||u<200){f=!1;break}_++}while(!f&&_<=10);return"#"+(16777216+i).toString(16).substr(1,6)};return{commatize:t,is_deferred:e,ServerStateDeferred:i,get_random_color:a}}.call(e,i,e,t),!(void 0!==a&&(t.exports=a))}).call(e,i(2),i(1))},function(t,e,i){var a,n;(function(o){a=[i(32),i(6),i(5)],n=function(t,e,i){t=t||window.BibtexParser;var a="citation",n=o.Model.extend(e.LoggableMixin).extend({_logNamespace:a,initialize:function(){var e=this.get("content"),i=t(e).entries[0];this.entry=i,this._fields={};var a=i.Fields;for(var n in a){var o=a[n],s=n.toLowerCase();this._fields[s]=o}},entryType:function(){return this.entry.EntryType},fields:function(){return this._fields}}),s=o.Collection.extend(e.LoggableMixin).extend({_logNamespace:a,urlRoot:Galaxy.root+"api",partial:!0,model:n}),r=s.extend({url:function(){return this.urlRoot+"/histories/"+this.history_id+"/citations"}}),l=s.extend({url:function(){return this.urlRoot+"/tools/"+this.tool_id+"/citations"},partial:!1});return{Citation:n,HistoryCitationCollection:r,ToolCitationCollection:l}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2))},function(t,e,i){var a,n;a=[i(4),i(7),i(49),i(23)],n=function(t,e,i,a){var n=i.extend({initialize:function(a){var n=this;i.prototype.initialize.call(this,t.merge({customize:function(t){t.buttons={execute:execute_btn=new e.Button({icon:"fa-check",tooltip:"Execute: "+t.name+" ("+t.version+")",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){execute_btn.wait(),n.portlet.disable(),n.submit(t,function(){execute_btn.unwait(),n.portlet.enable()})}})},t.job_id&&t.job_remap&&(t.inputs.rerun_remap_job_id={label:"Resume dependencies from this job",name:"rerun_remap_job_id",type:"select",display:"radio",ignore:"__ignore__",value:"__ignore__",options:[["Yes",t.job_id],["No","__ignore__"]],help:"The previous run of this tool failed and other tools were waiting for it to finish successfully. Use this option to resume those tools using the new output(s) of this tool run."})}},a))},submit:function(e,i){var n=this,o={tool_id:e.id,tool_version:e.version,inputs:this.data.create()};return this.trigger("reset"),n.validate(o)?(Galaxy.emit.debug("tool-form::submit()","Validation complete.",o),void t.request({type:"POST",url:Galaxy.root+"api/tools",data:o,success:function(t){i&&i(),n.$el.empty().append(a.success(t)),parent.Galaxy&&parent.Galaxy.currHistoryPanel&&parent.Galaxy.currHistoryPanel.refreshContents()},error:function(t){if(i&&i(),Galaxy.emit.debug("tool-form::submit","Submission failed.",t),t&&t.err_data){var e=n.data.matchResponse(t.err_data);for(var s in e){n.highlight(s,e[s]);break}}else n.modal.show({title:"Job submission failed",body:t&&t.err_msg||a.error(o),buttons:{Close:function(){n.modal.hide()}}})}})):(Galaxy.emit.debug("tool-form::submit()","Submission canceled. Validation failed."),void(i&&i()))},validate:function(t){var e=t.inputs,i=-1,a=null;for(var n in e){var o=e[n],s=this.data.match(n),r=this.field_list[s],l=this.input_list[s];if(s&&l&&r){if(!l.optional&&null==o)return this.highlight(s),!1;if(o&&o.batch){var c=o.values.length,h=c>0&&o.values[0]&&o.values[0].src;if(h)if(null===a)a=h;else if(a!==h)return this.highlight(s,"Please select either dataset or dataset list fields for all batch mode fields."),!1;if(i===-1)i=c;else if(i!==c)return this.highlight(s,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains "+c+" selection(s) while a previous field contains "+i+"."),!1}}else Galaxy.emit.debug("tool-form::validate()","Retrieving input objects failed.")}return!0}});return{View:n}}.apply(e,a),!(void 0!==n&&(t.exports=n))},function(t,e,i){var a,n;(function(i){a=[],n=function(){return{help:function(t){var e=i("").addClass("ui-form-help").append(t.help);return e.find("a").attr("target","_blank"),e},success:function(t){if(!t.jobs||!t.jobs.length)return this.error(t);
+var e=t.jobs.length,i="";i=1==e?"1 job has":e+" jobs have";var a='
'+i+" been successfully added to the queue - resulting in the following datasets:
";for(var n in t.outputs)a+='
'+t.outputs[n].hid+": "+t.outputs[n].name+"
";return a+="
You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.
"},error:function(t){return'
The server could not complete the request. Please contact the Galaxy Team if this error persists.
"},requirements:function(t){var e="This tool requires ";for(var i in t.requirements){var a=t.requirements[i];e+=a.name,a.version&&(e+=" (Version "+a.version+")"),ihere for more information.'}}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(1))},function(t,e,i){var a,n;(function(o,s){a=[i(4),i(11),i(7)],n=function(t,e,i){var a=o.View.extend({initialize:function(t){var a=this;this.options=t,this.name=t.name||"element",this.multiple=t.multiple||!1,this.message=new i.Message({cls:"ui-margin-top"}),this.portlet=new e.View({cls:"ui-portlet-section"}),this.select=new i.Select.View({optional:t.optional}),this.button=new i.ButtonIcon({icon:"fa fa-sign-in",floating:"left",tooltip:"Insert new "+this.name,onclick:function(){a.add({id:a.select.value(),name:a.select.text()})}}),this.setElement(this._template(t)),this.$(".ui-list-message").append(this.message.$el),this.$(".ui-list-portlet").append(this.portlet.$el),this.$(".ui-list-button").append(this.button.$el),this.$(".ui-list-select").append(this.select.$el)},value:function(t){if(void 0!==t){if(this.portlet.empty(),s.isArray(t))for(var e in t){var i=t[e],a=null,n=null;"string"!=s.type(i)?(a=i.id,n=i.name):a=n=i,null!=a&&this.add({id:a,name:n})}this._refresh()}var o=[];return this.$(".ui-list-id").each(function(){o.push({id:s(this).prop("id"),name:s(this).find(".ui-list-name").html()})}),0==o.length?null:o},add:function(e){var i=this;if(0===this.$('[id="'+e.id+'"]').length)if(t.validate(e.id)){var a=s(this._templateRow({id:e.id,name:e.name}));a.on("click",function(){a.remove(),i._refresh()}),a.on("mouseover",function(){a.addClass("portlet-highlight")}),a.on("mouseout",function(){a.removeClass("portlet-highlight")}),this.portlet.append(a),this._refresh()}else this.message.update({message:"Please select a valid "+this.name+".",status:"danger"});else this.message.update({message:"This "+this.name+" is already in the list."})},update:function(t){this.select.update(t)},_refresh:function(){this.$(".ui-list-id").length>0?(!this.multiple&&this.button.disable(),this.$(".ui-list-portlet").show()):(this.button.enable(),this.$(".ui-list-portlet").hide()),this.options.onchange&&this.options.onchange()},_template:function(t){return'
'},_templateRow:function(t){return'
'+t.name+"
"}});return{View:a}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1))},function(t,e,i){var a,n;(function(o,s){a=[i(4),i(16)],n=function(t,e){var i=o.View.extend({initialize:function(i){var a=this;this.options=t.merge(i,{visible:!0,data:[],id:t.uid(),error_text:"No options available.",wait_text:"Please wait...",multiple:!1}),this.setElement(''),this.$message=s(""),this.$options=s(this._template(i)),this.$menu=s(''),this.$el.append(this.$message),this.$el.append(this.$menu),this.$el.append(this.$options),this.options.multiple&&(this.all_button=new e.ButtonCheck({onclick:function(){a.$("input").prop("checked",0!==a.all_button.value()),a.trigger("change")}}),this.$menu.append(this.all_button.$el)),this.options.visible||this.$el.hide(),this.update(this.options.data),void 0!==this.options.value&&this.value(this.options.value),this.on("change",function(){this.options.onchange&&this.options.onchange(this.value())})},update:function(t){var e=this._getValue();if(this.$options.empty(),this._templateOptions)this.$options.append(this._templateOptions(t));else for(var i in t){var a=s(this._templateOption(t[i]));a.addClass("ui-option"),a.tooltip({title:t[i].tooltip,placement:"bottom"}),this.$options.append(a)}var n=this;this.$("input").on("change",function(){n.value(n._getValue()),n.trigger("change")}),this.value(e),this.unwait()},value:function(t){if(void 0!==t&&(this.$("input").prop("checked",!1),null!==t)){t instanceof Array||(t=[t]);for(var e in t)this.$('input[value="'+t[e]+'"]').first().prop("checked",!0)}var i=this._getValue();if(this.all_button){var a=i;a=a instanceof Array?a.length:0,this.all_button.value(a,this._size())}return i},exists:function(t){if(void 0!==t){t instanceof Array||(t=[t]);for(var e in t)if(this.$('input[value="'+t[e]+'"]').length>0)return!0}return!1},first:function(){var t=this.$("input").first();return t.length>0?t.val():null},wait:function(){0==this._size()&&(this._messageShow(this.options.wait_text,"info"),this.$options.hide(),this.$menu.hide())},unwait:function(){var t=this._size();0==t?(this._messageShow(this.options.error_text,"danger"),this.$options.hide(),this.$menu.hide()):(this._messageHide(),this.$options.css("display","inline-block"),this.$menu.show())},_getValue:function(){var e=[];return this.$(":checked").each(function(){e.push(s(this).val())}),t.validate(e)?this.options.multiple?e:e[0]:null},_size:function(){return this.$(".ui-option").length},_messageShow:function(t,e){this.$message.show(),this.$message.removeClass(),this.$message.addClass("ui-message alert alert-"+e),this.$message.html(t)},_messageHide:function(){this.$message.hide()},_template:function(){return''}}),a=i.extend({_templateOption:function(e){var i=t.uid();return'"}}),n={};n.View=a.extend({initialize:function(t){t.type="radio",a.prototype.initialize.call(this,t)}});var r={};r.View=a.extend({initialize:function(t){t.multiple=!0,t.type="checkbox",a.prototype.initialize.call(this,t)}});var l={};return l.View=i.extend({initialize:function(t){i.prototype.initialize.call(this,t)},value:function(t){return void 0!==t&&(this.$("input").prop("checked",!1),this.$("label").removeClass("active"),this.$('[value="'+t+'"]').prop("checked",!0).closest("label").addClass("active")),this._getValue()},_templateOption:function(t){var e="fa "+t.icon;t.label||(e+=" no-padding");var i='"},_template:function(){return''}}),{Base:i,BaseIcons:a,Radio:n,RadioButton:l,Checkbox:r}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1))},,function(t,e,i){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}function n(t,e,i){this.helpers=t||{},this.partials=e||{},this.decorators=i||{},l.registerDefaultHelpers(this),c.registerDefaultDecorators(this)}e.__esModule=!0,e.HandlebarsEnvironment=n;var o=i(8),s=i(9),r=a(s),l=i(70),c=i(68),h=i(78),d=a(h),u="4.0.11";e.VERSION=u;var p=7;e.COMPILER_REVISION=p;var g={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0"};e.REVISION_CHANGES=g;var f="[object Object]";n.prototype={constructor:n,logger:d.default,log:d.default.log,registerHelper:function(t,e){if(o.toString.call(t)===f){if(e)throw new r.default("Arg not supported with multiple helpers");o.extend(this.helpers,t)}else this.helpers[t]=e},unregisterHelper:function(t){delete this.helpers[t]},registerPartial:function(t,e){if(o.toString.call(t)===f)o.extend(this.partials,t);else{if("undefined"==typeof e)throw new r.default('Attempting to register a partial called "'+t+'" as undefined');this.partials[t]=e}},unregisterPartial:function(t){delete this.partials[t]},registerDecorator:function(t,e){if(o.toString.call(t)===f){if(e)throw new r.default("Arg not supported with multiple decorators");o.extend(this.decorators,t)}else this.decorators[t]=e},unregisterDecorator:function(t){delete this.decorators[t]}};var _=d.default.log;e.log=_,e.createFrame=o.createFrame,e.logger=d.default},,,,function(t,e,i){var a,n;(function(o,s,r){a=[i(4)],n=function(t){var e=o.View.extend({optionsDefault:{title_new:"",operations:null,onnew:null,max:null,onchange:null},initialize:function(e){this.visible=!1,this.$nav=null,this.$content=null,this.first_tab=null,this.current_id=null,this.options=t.merge(e,this.optionsDefault);var i=s(this._template(this.options));this.$nav=i.find(".tab-navigation"),this.$content=i.find(".tab-content"),this.setElement(i),this.list={};var a=this;if(this.options.operations&&s.each(this.options.operations,function(t,e){e.$el.prop("id",t),a.$nav.find(".operations").append(e.$el)}),this.options.onnew){var n=s(this._template_tab_new(this.options));this.$nav.append(n),n.tooltip({title:"Add a new tab",placement:"bottom",container:a.$el}),n.on("click",function(t){n.tooltip("hide"),a.options.onnew()})}},size:function(){return r.size(this.list)},current:function(){return this.$el.find(".tab-pane.active").attr("id")},add:function(t){var e=this,i=t.id,a=s(this._template_tab(t)),n=s(this._template_tab_content(t));if(this.list[i]=!!t.ondel,this.options.onnew?this.$nav.find("#new-tab").before(a):this.$nav.append(a),n.append(t.$el),this.$content.append(n),1==this.size()&&(a.addClass("active"),n.addClass("active"),this.first_tab=i),this.options.max&&this.size()>=this.options.max&&this.$el.find("#new-tab").hide(),t.ondel){var o=a.find("#delete");o.tooltip({title:"Delete this tab",placement:"bottom",container:e.$el}),o.on("click",function(){return o.tooltip("destroy"),e.$el.find(".tooltip").remove(),t.ondel(),!1})}a.on("click",function(a){a.preventDefault(),t.onclick?t.onclick():e.show(i)}),this.current_id||(this.current_id=i)},del:function(t){this.$el.find("#tab-"+t).remove(),this.$el.find("#"+t).remove(),this.first_tab==t&&(this.first_tab=null),null!=this.first_tab&&this.show(this.first_tab),this.list[t]&&delete this.list[t],this.size()
',"Warning: This is a experimental feature. Most Galaxy tools will not annotate"," citations explicitly at this time. When writing up your analysis, please manually"," review your histories and find all references"," that should be cited in order to completely describe your work. Also, please remember to",' cite Galaxy.',"
"].join("")}});return{CitationView:a,CitationListView:n}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2))},,,,,function(t,e,i){var a,n;(function(o,s,r){a=[i(4)],n=function(t){var e=o.Model.extend({initialize:function(t){this.app=t},checksum:function(){var t="",e=this;return this.app.section.$el.find(".section-row").each(function(){var i=s(this).attr("id"),a=e.app.field_list[i];a&&(t+=i+":"+JSON.stringify(a.value&&a.value())+":"+a.collapsed+";")}),t},create:function(){function t(t,e,i){a.flat_dict[t]=e,o[t]=i}function e(n,o){for(var s in o){var r=o[s];if(r.input){var l=r.input,c=n;switch(""!=n&&(c+="|"),c+=l.name,l.type){case"repeat":var h="section-",d=[],u=null;for(var p in r){var g=p.indexOf(h);g!=-1&&(g+=h.length,d.push(parseInt(p.substr(g))),u||(u=p.substr(0,g)))}d.sort(function(t,e){return t-e});var s=0;for(var f in d)e(c+"_"+s++,r[u+d[f]]);break;case"conditional":var _=a.app.field_list[l.id].value();t(c+"|"+l.test_param.name,l.id,_);var v=i(l,_);v!=-1&&e(c,o[l.id+"-section-"+v]);break;case"section":e(!l.flat&&c||"",r);break;default:var m=a.app.field_list[l.id];if(m&&m.value){var _=m.value();if((void 0===l.ignore||l.ignore!=_)&&(m.collapsed&&l.collapsible_value&&(_=l.collapsible_value),t(c,l.id,_),l.payload))for(var b in l.payload)t(b,l.id,l.payload[b])}}}}}var a=this,n={};this._iterate(this.app.section.$el,n);var o={};return this.flat_dict={},e("",n),o},match:function(t){return this.flat_dict&&this.flat_dict[t]},matchCase:function(t,e){return i(t,e)},matchModel:function(t,e){return n(t.inputs,this.flat_dict,e)},matchResponse:function(t){function e(t,n){if("string"==typeof n){var o=a.flat_dict[t];o&&(i[o]=n)}else for(var s in n){var r=s;if(""!==t){var l="|";n instanceof Array&&(l="_"),r=t+l+r}e(r,n[s])}}var i={},a=this;return e("",t),i},_iterate:function(t,e){var i=this,a=s(t).children();a.each(function(){var t=this,a=s(t).attr("id");if(s(t).hasClass("section-row")){var n=i.app.input_list[a];e[a]=n&&{input:n}||{},i._iterate(t,e[a])}else i._iterate(t,e)})}}),i=function(t,e){"boolean"==t.test_param.type&&(e="true"==e?t.test_param.truevalue||"true":t.test_param.falsevalue||"false");for(var i in t.cases)if(t.cases[i].value==e)return i;return-1},a=function(t,e,i,n){n=s.extend(!0,{},n),r.each(t,function(t){t&&t.type&&(n[t.name]=t)}),r.each(t,function(t){r.isObject(t)&&(t.type&&n[t[e]]?i(t,n[t[e]]):a(t,e,i,n))})},n=function(t,e,a){function n(t,o){for(var s in o){var r=o[s],l=r.name;switch(""!=t&&(l=t+"|"+l),r.type){case"repeat":for(var c in r.cache)n(l+"_"+c,r.cache[c]);break;case"conditional":var h=i(r,r.test_param&&r.test_param.value);h!=-1&&n(l,r.cases[h].inputs);break;case"section":n(l,r.inputs);break;default:var d=e[l];d&&a(d,r)}}}var o={};return n("",t),o};return{Manager:e,matchIds:n,matchContext:a}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1),i(3))},function(t,e,i){var a,n;(function(i){a=[],n=function(){return i.View.extend({initialize:function(t,e){this.app=t,this.field=e.field,this.text_enable=t.options.text_enable||"Enable",this.text_disable=t.options.text_disable||"Disable",this.cls_enable=t.options.cls_enable||"fa fa-caret-square-o-down",this.cls_disable=t.options.cls_disable||"fa fa-caret-square-o-up",this.setElement(this._template(e)),this.$field=this.$(".ui-form-field"),this.$preview=this.$(".ui-form-preview"),this.$collapsible=this.$(".ui-form-collapsible"),this.$collapsible_icon=this.$(".ui-form-collapsible").find(".icon"),this.$error_text=this.$(".ui-form-error-text"),this.$error=this.$(".ui-form-error"),this.$backdrop=this.$(".ui-form-backdrop"),this.$field.prepend(this.field.$el),this.field.collapsed=void 0!==e.collapsible_value&&JSON.stringify(e.value)==JSON.stringify(e.collapsible_value),this._refresh();var i=this;this.$collapsible.on("click",function(){i.field.collapsed=!i.field.collapsed,i._refresh()})},disable:function(t){this.$backdrop.show(),t&&this.$backdrop.css({opacity:0,cursor:"default"})},error:function(t){this.$error_text.html(t),this.$error.show(),this.$el.addClass("ui-error")},reset:function(){this.$error.hide(),this.$el.removeClass("ui-error")},_refresh:function(){this.$collapsible_icon.removeClass().addClass("icon"),this.field.collapsed?(this.$field.hide(),this.$preview.show(),this._tooltip(this.text_enable,this.cls_enable)):(this.$field.fadeIn("fast"),this.$preview.hide(),this._tooltip(this.text_disable,this.cls_disable)),this.app.trigger("change")},_tooltip:function(t,e){this.$collapsible_icon.addClass(e).tooltip({placement:"bottom"}).attr("data-original-title",t).tooltip("fixTitle").tooltip("hide")},_template:function(t){var e='
"}})}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2))},function(t,e,i){var a,n;(function(o,s){a=[i(4),i(7),i(43),i(56),i(55),i(52)],n=function(t,e,i,a,n,r){return o.Model.extend({types:{text:"_fieldText",select:"_fieldSelect",data_column:"_fieldSelect",genomebuild:"_fieldSelect",data:"_fieldData",data_collection:"_fieldData",integer:"_fieldSlider",float:"_fieldSlider",boolean:"_fieldBoolean",drill_down:"_fieldDrilldown",color:"_fieldColor",hidden:"_fieldHidden",hidden_data:"_fieldHidden",baseurl:"_fieldHidden",library_data:"_fieldLibrary",ftpfile:"_fieldFtp"},initialize:function(t,e){this.app=t},create:function(t){void 0===t.value&&(t.value=null),void 0===t.default_value&&(t.default_value=t.value);var e=null,i=this.types[t.type];return i&&"function"==typeof this[i]&&(e=this[i].call(this,t)),e||(this.app.incompatible=!0,e=t.options?this._fieldSelect(t):this._fieldText(t),Galaxy.emit.debug("form-parameters::_addRow()","Auto matched field type ("+t.type+").")),void 0!==t.value&&e.value(t.value),e},_fieldData:function(t){var e=this;return new i.View(this.app,{id:"field-"+t.id,extensions:t.extensions,optional:t.optional,multiple:t.multiple,type:t.type,data:t.options,onchange:function(){e.app.trigger("change")}})},_fieldSelect:function(t){if(t.is_workflow)return this._fieldText(t);"data_column"==t.type&&(t.error_text="Missing columns in referenced dataset.");var i=[];for(var a in t.options){var n=t.options[a];i.push({label:n[0],value:n[1]})}var o=e.Select;switch(t.display){case"checkboxes":o=e.Checkbox;break;case"radio":o=e.Radio}var s=this;return new o.View({id:"field-"+t.id,data:i,error_text:t.error_text||"No options available",optional:t.optional&&null===t.default_value,multiple:t.multiple,optional:t.optional,searchable:t.searchable,onchange:function(){s.app.trigger("change")}})},_fieldDrilldown:function(t){if(t.is_workflow)return this._fieldText(t);var i=this;return new e.Drilldown.View({id:"field-"+t.id,data:t.options,display:t.display,onchange:function(){i.app.trigger("change")}})},_fieldText:function(i){if(i.options)if(i.area=i.multiple,t.validate(i.value)){if(s.isArray(i.value)){var a="";for(var n in i.value){if(a+=String(i.value[n]),!i.multiple)break;a+="\n"}i.value=a}}else i.value=null;var o=this;return new e.Input({id:"field-"+i.id,area:i.area,onchange:function(){o.app.trigger("change")}})},_fieldSlider:function(t){var i=this;return new e.Slider.View({id:"field-"+t.id,precise:"float"==t.type,is_workflow:t.is_workflow,min:t.min,max:t.max,onchange:function(){i.app.trigger("change")}})},_fieldHidden:function(t){return new e.Hidden({id:"field-"+t.id,info:t.info})},_fieldBoolean:function(t){var i=this;return new e.RadioButton.View({id:"field-"+t.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:function(){i.app.trigger("change")}})},_fieldColor:function(t){var e=this;return new r({id:"field-"+t.id,onchange:function(){e.app.trigger("change")}})},_fieldLibrary:function(t){var e=this;return new a.View({id:"field-"+t.id,optional:t.optional,multiple:t.multiple,onchange:function(){e.app.trigger("change")}})},_fieldFtp:function(t){var e=this;return new n.View({id:"field-"+t.id,optional:t.optional,multiple:t.multiple,onchange:function(){e.app.trigger("change")}})}})}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1))},function(t,e,i){var a,n;(function(o,s,r){a=[i(4),i(17),i(11),i(7)],n=function(t,e,i,a){var n=o.View.extend({initialize:function(i){this.options=t.merge(i,{title:"Section",empty_text:"Not available.",max:null,min:null}),this.setElement("");this.button_new=new a.ButtonIcon({icon:"fa-plus",title:"Insert "+i.title_new,tooltip:"Add new "+i.title_new+" block",floating:"clear",onclick:function(){i.onnew&&i.onnew()}}),this.table=new e.View({cls:"ui-table-plain",content:""}),this.$el.append(this.table.$el),this.$el.append(s("").append(this.button_new.$el)),this.list={},this.n=0},size:function(){return this.n},add:function(t){if(!t.id||this.list[t.id])return void Galaxy.emit.debug("form-repeat::add()","Duplicate repeat block id.");this.n++;var e=new a.ButtonIcon({icon:"fa-trash-o",tooltip:"Delete this repeat block",cls:"ui-button-icon-plain",onclick:function(){t.ondel&&t.ondel()}}),n=new i.View({id:t.id,title:"placeholder",cls:"ui-portlet-repeat",operations:{button_delete:e}});n.append(t.$el),n.$el.addClass("section-row"),this.list[t.id]=n,this.table.add(n.$el),this.table.append("row_"+t.id,!0),this.options.max>0&&this.n>=this.options.max&&this.button_new.disable(),this._refresh()},del:function(t){if(!this.list[t])return void Galaxy.emit.debug("form-repeat::del()","Invalid repeat block id.");this.n--;var e=this.table.get("row_"+t);e.remove(),delete this.list[t],this.button_new.enable(),this._refresh()},hideOptions:function(){this.button_new.$el.hide(),r.each(this.list,function(t){t.hideOperation("button_delete")}),r.isEmpty(this.list)&&this.$el.append(s("").addClass("ui-form-info").html(this.options.empty_text))},_refresh:function(){var t=0;for(var e in this.list){var i=this.list[e];i.title(++t+": "+this.options.title),this.n>this.options.min?i.showOperation("button_delete"):i.hideOperation("button_delete")}}});return{View:n}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1),i(3))},function(t,e,i){var a,n;(function(o,s,r,l){a=[i(4),i(17),i(7),i(11),i(41),i(39),i(40)],n=function(t,e,i,a,n,c,h){var d=o.View.extend({initialize:function(t,i){this.app=t,this.inputs=i.inputs,i.cls="ui-table-plain",i.cls_tr="section-row",this.table=new e.View(i),this.parameters=new h(t,i),this.setElement(this.table.$el),this.render()},render:function(){this.table.delAll();for(var t in this.inputs)this.add(this.inputs[t])},add:function(e){var i=s.extend(!0,{},e);i.id=e.id=t.uid(),this.app.input_list[i.id]=i;var a=i.type;switch(a){case"conditional":this._addConditional(i);break;case"repeat":this._addRepeat(i);break;case"section":this._addSection(i);break;default:this._addRow(i)}},_addConditional:function(t){var e=this;t.test_param.id=t.id,this.app.options.sustain_conditionals&&(t.test_param.disabled=!0);var i=this._addRow(t.test_param);i.options.onchange=function(i){var a=e.app.data.matchCase(t,i);for(var n in t.cases){var o=t.cases[n],s=t.id+"-section-"+n,r=e.table.get(s),l=!1;for(var c in o.inputs)if(!o.inputs[c].hidden){l=!0;break}n==a&&l?r.fadeIn("fast"):r.hide()}e.app.trigger("change")};for(var a in t.cases){var n=t.id+"-section-"+a,o=new d(this.app,{inputs:t.cases[a].inputs});o.$el.addClass("ui-table-section"),this.table.add(o.$el),this.table.append(n)}i.trigger("change")},_addRepeat:function(t){function e(e){var n=t.id+"-section-"+a++,s=new d(i.app,{inputs:e});o.add({id:n,$el:s.$el,ondel:function(){o.del(n),i.app.trigger("change")}})}for(var i=this,a=0,o=new n.View({title:t.title||"Repeat",title_new:t.title||"",min:t.min,max:t.max,onnew:function(){e(t.inputs),i.app.trigger("change")}}),s=r.size(t.cache),l=0;l").addClass("ui-form-info").html(t.help)),s.setOperation("button_visible",function(){s.collapsed?s.expand():s.collapse()}),s.on("expanded",function(){o.setIcon("fa-eye")}),s.on("collapsed",function(){o.setIcon("fa-eye-slash")}),this.app.on("expand",function(t){s.$("#"+t).length>0&&s.expand()}),t.expanded&&s.expand(),this.table.add(s.$el),this.table.append(t.id)},_addRow:function(t){var e=t.id,i=this.parameters.create(t);this.app.field_list[e]=i;var a=new c(this.app,{name:t.name,label:t.label||t.name,value:t.value,default_value:t.default_value,text_value:t.text_value||t.value,collapsible_value:t.collapsible_value,collapsible_preview:t.collapsible_preview,help:t.help,argument:t.argument,disabled:t.disabled,field:i});return this.app.element_list[e]=a,this.table.add(a.$el),this.table.append(e),t.hidden&&this.table.get(e).hide(),i}});return{View:d}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1),i(3),i(1))},function(t,e,i){var a,n;(function(o,s,r){a=[i(4),i(7),i(31)],n=function(t,e,i){var a=o.View.extend({initialize:function(i,a){this.app=i,this.options=a,this.history={};var n=this;this.setElement(''),this.list={};var o=[];"data_collection"==a.type?this.mode="collection":a.multiple?this.mode="multiple":this.mode="single",this.current=this.mode,this.list={};var l=t.textify(a.extensions),c="No dataset available.";l&&(c="No "+l+" dataset available.");var h="No dataset list available.";if(l&&(h="No "+l+" dataset collection available."),"single"==this.mode&&(o.push({icon:"fa-file-o",value:"single",tooltip:"Single dataset"}),this.select_single=new e.Select.View({optional:a.optional,error_text:c,onchange:function(){n.trigger("change")}}),this.list.single={field:this.select_single,type:"hda"}),"single"!=this.mode&&"multiple"!=this.mode||(o.push({icon:"fa-files-o",value:"multiple",tooltip:"Multiple datasets"}),this.select_multiple=new e.Select.View({multiple:!0,searchable:!1,optional:a.optional,error_text:c,onchange:function(){n.trigger("change")}}),this.list.multiple={field:this.select_multiple,type:"hda"}),"single"==this.mode||"multiple"==this.mode||"collection"==this.mode){o.push({icon:"fa-folder-o",value:"collection",tooltip:"Dataset collection"});var d="multiple"==this.mode;this.select_collection=new e.Select.View({error_text:h,multiple:d,searchable:!1,optional:a.optional,onchange:function(){n.trigger("change")}}),this.list.collection={field:this.select_collection,type:"hdca"}}this.button_type=new e.RadioButton.View({value:this.current,data:o,onchange:function(t){n.current=t,n.refresh(),n.trigger("change")}}),this.$batch=s(this.template_batch());var u=r.size(this.list),p=0;u>1&&(this.$el.append(this.button_type.$el),p=Math.max(0,35*r.size(this.list))+"px");for(var g in this.list)this.$el.append(this.list[g].field.$el.css({"margin-left":p}));this.$el.append(this.$batch.css({"margin-left":p})),this.update(a.data),void 0!==this.options.value&&this.value(this.options.value),this.refresh(),this.on("change",function(){a.onchange&&a.onchange(n.value())})},wait:function(){for(var t in this.list)this.list[t].field.wait()},unwait:function(){for(var t in this.list)this.list[t].field.unwait()},update:function(t){function e(t,e){if(t){var a=[];for(var n in e){var o=e[n];a.push({hid:o.hid,label:o.hid+": "+o.name,value:o.id}),i.history[o.id+"_"+o.src]=o}t.add(a,function(t,e){return e.hid-t.hid})}}var i=this;e(this.select_single,t.hda),e(this.select_multiple,t.hda),e(this.select_collection,t.hdca)},value:function(t){if(void 0!==t)if(t&&t.values)try{var e=[];for(var i in t.values)e.push(t.values[i].id);t&&t.values.length>0&&"hdca"==t.values[0].src?(this.current="collection",this.select_collection.value(e)):"multiple"==this.mode?(this.current="multiple",this.select_multiple.value(e)):(this.current="single",this.select_single.value(e[0]))}catch(t){Galaxy.emit.debug("tools-select-content::value()","Skipped.")}else for(var i in this.list)this.list[i].field.value(null);this.refresh();var a=this._select().value();if(null===a)return null;if(a instanceof Array||(a=[a]),0===a.length)return null;var n={batch:this._batch(),values:[]};for(var i in a){var o=this.history[a[i]+"_"+this.list[this.current].type];if(!o)return null;n.values.push(o)}return n.values.sort(function(t,e){return t.hid-e.hid}),n},refresh:function(){this.button_type.value(this.current);for(var t in this.list){var e=this.list[t].field.$el;this.current==t?e.show():e.hide()}this._batch()?this.$batch.show():this.$batch.hide()},_select:function(){return this.list[this.current].field},_batch:function(){if("collection"==this.current){var t=this.history[this._select().value()+"_hdca"];if(t&&t.map_over_type)return!0}return"single"!=this.current&&"single"==this.mode},template_batch:function(){return'
This is a batch mode input field. A separate job will be triggered for each dataset.
'}});return{View:a}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1),i(3))},function(t,e,i){var a,n;(function(o,s,r){a=[i(4),i(11),i(7),i(42),i(38)],n=function(t,e,i,a,n){return o.View.extend({initialize:function(e){this.options=t.merge(e,{initial_errors:!1,cls:"ui-portlet-limited",icon:""}),this.modal=parent.Galaxy&&parent.Galaxy.modal||new i.Modal.View,this.setElement(""),this.render()},update:function(t){var e=this;this.data.matchModel(t,function(t,i){var a=e.input_list[t];if(a&&a.options&&!s.isEqual(a.options,i.options)){a.options=i.options;var n=e.field_list[t];if(n.update){var o=[];if(["data","data_collection","drill_down"].indexOf(a.type)!=-1)o=a.options;else for(var r in i.options){var l=i.options[r];l.length>2&&o.push({label:l[0],value:l[1]})}n.update(o),n.trigger("change"),Galaxy.emit.debug("form-view::update()","Updating options for "+t)}}})},wait:function(t){for(var e in this.input_list){var i=this.field_list[e],a=this.input_list[e];a.is_dynamic&&i.wait&&i.unwait&&(t?i.wait():i.unwait())}},highlight:function(t,e,i){var a=this.element_list[t];if(a&&(a.error(e||"Please verify this parameter."),this.trigger("expand",t),!i))if(self==top){var n=this.$el.parents().filter(function(){return"auto"==r(this).css("overflow")}).first();n.animate({scrollTop:n.scrollTop()+a.$el.offset().top-50},500)}else r("html, body").animate({scrollTop:a.$el.offset().top-20},500)},errors:function(t){if(this.trigger("reset"),t&&t.errors){var e=this.data.matchResponse(t.errors);for(var i in this.element_list){this.element_list[i];e[i]&&this.highlight(i,e[i],!0)}}},render:function(){var t=this;this.off("change"),this.off("reset"),this.field_list={},this.input_list={},this.element_list={},this.data=new n.Manager(this),this._renderForm(),this.data.create(),this.options.initial_errors&&this.errors(this.options);var e=this.data.checksum();return this.on("change",function(){var i=t.data.checksum();i!=e&&(e=i,t.options.onchange&&t.options.onchange())}),this.on("reset",function(){for(var t in this.element_list)this.element_list[t].reset()}),this},_renderForm:function(){this.message=new i.Message,this.section=new a.View(this,{inputs:this.options.inputs}),r(".tooltip").remove(),this.portlet=new e.View({icon:this.options.icon,title:this.options.title,cls:this.options.cls,operations:this.options.operations,buttons:this.options.buttons,collapsible:this.options.collapsible,collapsed:this.options.collapsed}),this.portlet.append(this.message.$el.addClass("ui-margin-top")),this.portlet.append(this.section.$el),this.$el.empty(),this.$el.append(this.portlet.$el),this.options.message&&this.message.update({persistent:!0,status:"warning",message:this.options.message}),Galaxy.emit.debug("form-view::initialize()","Completed")}})}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(3),i(1))},,,,,function(t,e,i){var a,n;(function(o){a=[i(4),i(60),i(7),i(44),i(23),i(21),i(33)],n=function(t,e,i,a,n,s,r){return a.extend({initialize:function(t){var i=this;a.prototype.initialize.call(this,t),this.deferred=new e,t.inputs?(this._buildForm(t),t.needs_update&&this.deferred.execute(function(t){i._updateModel(t)})):this.deferred.execute(function(e){i._buildModel(e,t,!0)})},remove:function(){var t=this;this.$el.hide(),this.deferred.execute(function(){a.prototype.remove.call(t),Galaxy.emit.debug("tool-form-base::remove()","Destroy view.")})},_buildForm:function(e){var i=this;this.options=t.merge(e,this.options),this.options=t.merge({icon:void 0===e.icon&&"fa-wrench"||"",title:""+e.name+" "+e.description+" (Galaxy Version "+e.version+")",operations:this._operations(),onchange:function(){i.deferred.reset(),i.deferred.execute(function(t){i._updateModel(t)})}},this.options),this.options.customize&&this.options.customize(this.options),this.render(),this.options.collapsible||this.$el.append(o("").addClass("ui-margin-top-large").append(this._footer()))},_buildModel:function(e,a,n){var s=this;this.options.id=a.id,this.options.version=a.version;var r="",l={};a.job_id?r=Galaxy.root+"api/jobs/"+a.job_id+"/build_for_rerun":(r=Galaxy.root+"api/tools/"+a.id+"/build",Galaxy.params&&Galaxy.params.tool_id==a.id&&(l=o.extend({},Galaxy.params),a.version&&(l.tool_version=a.version))),t.request({type:"GET",url:r,data:l,success:function(t){return t=t.tool_model||t,t.display?(s._buildForm(t),!n&&s.message.update({status:"success",message:"Now you are using '"+s.options.name+"' version "+s.options.version+", id '"+s.options.id+"'.",persistent:!1}),Galaxy.emit.debug("tool-form-base::initialize()","Initial tool model ready.",t),void e.resolve()):void(window.location=Galaxy.root)},error:function(t,a){var n=t&&t.err_msg||"Uncaught error.";401==a.status?window.location=Galaxy.root+"user/login?"+o.param({redirect:Galaxy.root+"?tool_id="+s.options.id}):s.$el.is(":empty")?s.$el.prepend(new i.Message({message:n,status:"danger",persistent:!0,large:!0}).$el):Galaxy.modal.show({title:"Tool request failed",body:n,buttons:{Close:function(){Galaxy.modal.hide()}}}),Galaxy.emit.debug("tool-form::initialize()","Initial tool model request failed.",t),e.reject()}})},_updateModel:function(e){var i=this,a=this.options.update_url||Galaxy.root+"api/tools/"+this.options.id+"/build",n={tool_id:this.options.id,tool_version:this.options.version,inputs:o.extend(!0,{},i.data.create())};this.wait(!0),Galaxy.emit.debug("tool-form-base::_updateModel()","Sending current state.",n),t.request({type:"POST",url:a,data:n,success:function(t){i.update(t.tool_model||t),i.options.update&&i.options.update(t),i.wait(!1),Galaxy.emit.debug("tool-form-base::_updateModel()","Received new model.",t),e.resolve()},error:function(t){Galaxy.emit.debug("tool-form-base::_updateModel()","Refresh request failed.",t),e.reject()}})},_operations:function(){var t=this,e=this.options,a=new i.ButtonMenu({icon:"fa-cubes",title:!e.narrow&&"Versions"||null,tooltip:"Select another tool version"});if(!e.sustain_version&&e.versions&&e.versions.length>1)for(var o in e.versions){var s=e.versions[o];s!=e.version&&a.addMenu({title:"Switch to "+s,version:s,icon:"fa-cube",onclick:function(){var i=e.id.replace(e.version,this.version),a=this.version;t.deferred.reset(),t.deferred.execute(function(e){t._buildModel(e,{id:i,version:a})})}})}else a.$el.hide();var r=new i.ButtonMenu({icon:"fa-caret-down",title:!e.narrow&&"Options"||null,tooltip:"View available options"});return e.biostar_url&&(r.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(e.biostar_url+"/p/new/post/")}}),r.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(e.biostar_url+"/local/search/page/?q="+e.name)}})),r.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+Galaxy.root+"root?tool_id="+e.id)}}),Galaxy.user&&Galaxy.user.get("is_admin")&&r.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=Galaxy.root+"api/tools/"+e.id+"/download"}}),e.requirements&&e.requirements.length>0&&r.addMenu({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){this.visible?(this.visible=!1,t.message.update({message:""})):(this.visible=!0,t.message.update({persistent:!0,message:n.requirements(e),status:"info"}))}}),e.sharable_url&&r.addMenu({icon:"fa-external-link",title:"See in Tool Shed",tooltip:"Access the repository",onclick:function(){window.open(e.sharable_url)}}),{menu:r,versions:a}},_footer:function(){var t=this.options,e=o("").append(n.help(t));if(t.citations){var i=o(""),a=new s.ToolCitationCollection;a.tool_id=t.id;var l=new r.CitationListView({el:i,collection:a});l.render(),a.fetch(),e.append(i)}return e}})}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(1))},function(t,e,i){var a,n;(function(o,s){a=[i(3),i(20),i(14),i(22),i(64),i(65),i(63),i(66)],n=function(t,e,i,a,n,r,l,c){var h={hidden:!1,show:function(){this.set("hidden",!1)},hide:function(){this.set("hidden",!0)},toggle:function(){this.set("hidden",!this.get("hidden"))},is_visible:function(){return!this.attributes.hidden}},d=o.Model.extend({defaults:{name:null,label:null,type:null,value:null,html:null,num_samples:5},initialize:function(t){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new d(this.toJSON())},set_value:function(t){this.set("value",t||"")}}),u=o.Collection.extend({model:d}),p=d.extend({}),g=d.extend({set_value:function(t){this.set("value",parseInt(t,10))},get_samples:function(){return d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}}),f=g.extend({set_value:function(t){this.set("value",parseFloat(t))}}),_=d.extend({get_samples:function(){return t.map(this.get("options"),function(t){return t[0]})}});d.subModelTypes={integer:g,float:f,data:p,select:_};var v=o.Model.extend({defaults:{id:null,name:null,description:null,target:null,inputs:[],outputs:[]},urlRoot:Galaxy.root+"api/tools",initialize:function(e){this.set("inputs",new u(t.map(e.inputs,function(t){var e=d.subModelTypes[t.type]||d;return new e(t)})))},toJSON:function(){var t=o.Model.prototype.toJSON.call(this);return t.inputs=this.get("inputs").map(function(t){return t.toJSON()}),t},remove_inputs:function(t){var e=this,i=e.get("inputs").filter(function(e){return t.indexOf(e.get("type"))!==-1});e.get("inputs").remove(i)},copy:function(t){var e=new v(this.toJSON());if(t){var i=new o.Collection;e.get("inputs").each(function(t){t.get_samples()&&i.push(t)}),e.set("inputs",i)}return e},apply_search_results:function(e){return t.indexOf(e,this.attributes.id)!==-1?this.show():this.hide(),this.is_visible()},set_input_value:function(t,e){this.get("inputs").find(function(e){return e.get("name")===t}).set("value",e)},set_input_values:function(e){var i=this;t.each(t.keys(e),function(t){i.set_input_value(t,e[t])})},run:function(){return this._run()},rerun:function(t,e){return this._run({action:"rerun",target_dataset_id:t.id,regions:e})},get_inputs_dict:function(){var t={};return this.get("inputs").each(function(e){t[e.get("name")]=e.get("value")}),t},_run:function(a){var n=t.extend({tool_id:this.id,inputs:this.get_inputs_dict()},a),o=s.Deferred(),r=new e.ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(n),dataType:"json",
+contentType:"application/json",type:"POST"},interval:2e3,success_fn:function(t){return"pending"!==t}});return s.when(r.go()).then(function(t){o.resolve(new i.DatasetCollection(t))}),o}});t.extend(v.prototype,h);var m=(o.View.extend({}),o.Collection.extend({model:v})),b=o.Model.extend(h),w=o.Model.extend({defaults:{elems:[],open:!1},clear_search_results:function(){t.each(this.attributes.elems,function(t){t.show()}),this.show(),this.set("open",!1)},apply_search_results:function(e){var i,a=!0;t.each(this.attributes.elems,function(t){t instanceof b?(i=t,i.hide()):t instanceof v&&t.apply_search_results(e)&&(a=!1,i&&i.show())}),a?this.hide():(this.show(),this.set("open",!0))}});t.extend(w.prototype,h);var y=o.Model.extend({defaults:{search_hint_string:"search tools",min_chars_for_search:3,spinner_url:"",clear_btn_url:"",search_url:"",visible:!0,query:"",results:null,clear_key:27},urlRoot:Galaxy.root+"api/tools",initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var t=this.attributes.query;if(t.length");if(t.append(r(this.model.toJSON())),"upload1"===this.model.id)t.find("a").on("click",function(t){t.preventDefault(),Galaxy.upload.show()});else if("Tool"===this.model.get("model_class")){var e=this;t.find("a").on("click",function(t){t.preventDefault();var i=new a.View({id:e.model.id,version:e.model.get("version")});i.deferred.execute(function(){Galaxy.app.display(i)})})}return this.$el.append(t),this}}),E=k.extend({tagName:"div",className:"toolPanelLabel",render:function(){return this.$el.append(s("").text(this.model.attributes.text)),this}}),S=k.extend({tagName:"div",className:"toolSectionWrapper",initialize:function(){k.prototype.initialize.call(this),this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(l(this.model.toJSON()));var e=this.$el.find(".toolSectionBody");return t.each(this.model.attributes.elems,function(t){if(t instanceof v){var i=new C({model:t,className:"toolTitle"});i.render(),e.append(i.$el)}else if(t instanceof b){var a=new E({model:t});a.render(),e.append(a.$el)}}),this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast")}}),T=o.View.extend({tagName:"div",id:"tool-search",className:"bar",events:{click:"focus_and_select","keyup :input":"query_changed","click #search-clear-btn":"clear"},render:function(){return this.$el.append(c(this.model.toJSON())),this.model.is_visible()||this.$el.hide(),this.$el.find("[title]").tooltip(),this},focus_and_select:function(){this.$el.find(":input").focus().select()},clear:function(){return this.model.clear_search(),this.$el.find(":input").val(""),this.focus_and_select(),!1},query_changed:function(t){return this.model.attributes.clear_key&&this.model.attributes.clear_key===t.which?(this.clear(),!1):void this.model.set("query",this.$el.find(":input").val())}}),$=o.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.model.get("tool_search").on("change:results",this.handle_search_results,this)},render:function(){var t=this,e=new T({model:this.model.get("tool_search")});return e.render(),t.$el.append(e.$el),this.model.get("layout").each(function(e){if(e instanceof w){var i=new S({model:e});i.render(),t.$el.append(i.$el)}else if(e instanceof v){var a=new C({model:e,className:"toolTitleNoSection"});a.render(),t.$el.append(a.$el)}else if(e instanceof b){var n=new E({model:e});n.render(),t.$el.append(n.$el)}}),t.$el.find("a.tool-link").click(function(e){var i=s(this).attr("class").split(/\s+/)[0],a=t.model.get("tools").get(i);t.trigger("tool_link_click",e,a)}),this},handle_search_results:function(){var t=this.model.get("tool_search").get("results");t&&0===t.length?s("#search-no-results").show():s("#search-no-results").hide()}}),M=o.View.extend({className:"toolForm",render:function(){this.$el.children().remove(),this.$el.append(n(this.model.toJSON()))}});o.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new $({collection:this.collection}),this.tool_form_view=new M},render:function(){this.tool_panel_view.render(),this.tool_panel_view.$el.css("float","left"),this.$el.append(this.tool_panel_view.$el),this.tool_form_view.$el.hide(),this.$el.append(this.tool_form_view.$el);var t=this;this.tool_panel_view.on("tool_link_click",function(e,i){e.preventDefault(),t.show_tool(i)})},show_tool:function(t){var e=this;t.fetch().done(function(){e.tool_form_view.model=t,e.tool_form_view.render(),e.tool_form_view.$el.show(),s("#left").width("650px")})}});return{ToolParameter:d,IntegerToolParameter:g,SelectToolParameter:_,Tool:v,ToolCollection:m,ToolSearch:y,ToolPanel:x,ToolPanelView:$,ToolFormView:M}}.apply(e,a),!(void 0!==n&&(t.exports=n))}).call(e,i(2),i(1))},,function(t,e,i){var a,n;(function(o,s){a=[i(4)],n=function(t){return o.View.extend({colors:{standard:["c00000","ff0000","ffc000","ffff00","92d050","00b050","00b0f0","0070c0","002060","7030a0"],base:["ffffff","000000","eeece1","1f497d","4f81bd","c0504d","9bbb59","8064a2","4bacc6","f79646"],theme:[["f2f2f2","7f7f7f","ddd9c3","c6d9f0","dbe5f1","f2dcdb","ebf1dd","e5e0ec","dbeef3","fdeada"],["d8d8d8","595959","c4bd97","8db3e2","b8cce4","e5b9b7","d7e3bc","ccc1d9","b7dde8","fbd5b5"],["bfbfbf","3f3f3f","938953","548dd4","95b3d7","d99694","c3d69b","b2a2c7","92cddc","fac08f"],["a5a5a5","262626","494429","17365d","366092","953734","76923c","5f497a","31859b","e36c09"],["7f7f7e","0c0c0c","1d1b10","0f243e","244061","632423","4f6128","3f3151","205867","974806"]]},initialize:function(e){this.options=t.merge(e,{}),this.setElement(this._template()),this.$panel=this.$(".ui-color-picker-panel"),this.$view=this.$(".ui-color-picker-view"),this.$value=this.$(".ui-color-picker-value"),this.$header=this.$(".ui-color-picker-header"),this._build(),this.visible=!1,this.value(this.options.value),this.$boxes=this.$(".ui-color-picker-box");var i=this;this.$boxes.on("click",function(){i.value(s(this).css("background-color")),i.$header.trigger("click")}),this.$header.on("click",function(){i.visible=!i.visible,i.visible?i.$view.fadeIn("fast"):i.$view.fadeOut("fast")})},value:function(t){return void 0!==t&&null!==t&&(this.$value.css("background-color",t),this.$(".ui-color-picker-box").empty(),this.$(this._getValue()).html(this._templateCheck()),this.options.onchange&&this.options.onchange(t)),this._getValue()},_getValue:function(){function t(t){return("0"+parseInt(t).toString(16)).slice(-2)}var e=this.$value.css("background-color");return e=e.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/),e?"#"+t(e[1])+t(e[2])+t(e[3]):null},_build:function(){this._content({label:"Theme Colors",colors:this.colors.base,padding:10});for(var t in this.colors.theme){var e={};0==t?e.bottom=!0:t!=this.colors.theme.length-1?(e.top=!0,e.bottom=!0):(e.top=!0,e.padding=5),e.colors=this.colors.theme[t],this._content(e)}this._content({label:"Standard Colors",colors:this.colors.standard,padding:5})},_content:function(t){var e=(t.label,t.colors),i=t.padding,a=t.top,n=t.bottom,o=s(this._templateContent()),r=o.find(".label");t.label?r.html(t.label):r.hide();var l=o.find(".line");this.$panel.append(o);for(var c in e){var h=s(this._templateBox(e[c]));a&&(h.css("border-top","none"),h.css("border-top-left-radius","0px"),h.css("border-top-right-radius","0px")),n&&(h.css("border-bottom","none"),h.css("border-bottom-left-radius","0px"),h.css("border-bottom-right-radius","0px")),l.append(h)}return i&&l.css("padding-bottom",i),o},_templateCheck:function(){return''},_templateContent:function(){return'
").addClass("param-row").appendTo(parent_div),i=o("").attr("value","Run on complete dataset").appendTo(e),a=o("").attr("value","Run on visible region").appendTo(e);a.click(function(){t.run_on_region()}),i.click(function(){t.run_on_dataset()}),tool.is_visible()&&this.$el.show()},set_visible:function(){this.$el.toggle(this.model.is_visible())},update_params:function(){for(var t=0;t").append(a),this.data=n,this.stale=!1};G.prototype.predisplay_actions=function(){};var D=function(t,e,i,a,n){G.call(this,t,e,i,a,n)};D.prototype.predisplay_actions=function(){};var I=function(t,e,i,a,n,o,s,r,l,c,h){G.call(this,t,e,i,a,n),this.mode=o,this.all_slotted=r,this.feature_mapper=l,this.has_icons=!1,this.incomplete_features=c,this.other_tiles_features_drawn={},this.seq_data=h};u(I.prototype,G.prototype),I.prototype.predisplay_actions=function(){};var Y=function(t,i,a){u(a,{drag_handle_class:"draghandle"}),R.call(this,t,i,a),this.dataset=null,a.dataset&&(this.dataset=a.dataset instanceof s.Model?a.dataset:new c.Dataset(a.dataset)),this.dataset_check_type="converted_datasets_state",this.data_url_extra_params={},this.data_query_wait="data_query_wait"in a?a.data_query_wait:w,this.data_manager="data_manager"in a?a.data_manager:new e.GenomeDataManager({dataset:this.dataset,genome:new e.Genome({key:t.dbkey,chroms_info:{chrom_info:t.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}),this.min_height_px=16,this.max_height_px=800,this.visible_height_px=this.config.get_value("height"),this.content_div=o("
").appendTo(this.container_div),this.container&&(this.container.content_div.append(this.container_div),"resize"in a&&!a.resize||this.add_resize_handle())};u(Y.prototype,R.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},R.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"application-dock-270",on_click_fn:function(t){t.view.set_overview(t)}},R.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"ui-slider-050",on_click_fn:function(t){t.filters_manager.visible()?t.filters_manager.clear_filters():t.filters_manager.init_filters(),t.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(t){t.tool.toggle(),t.tool.is_visible()?t.set_name(t.config.get_value("name")+t.tool_region_and_parameters_str()):t.revert_name(),o(".tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(i){var a="Tool:"+i.tool.get("name")+" Dataset:"+i.config.get_value("name")+' Region(s): ',n=function(){Galaxy.modal.hide(),o(window).unbind("keypress.check_enter_esc")},r=function(){var a,n=o('select[name="regions"] option:selected').val(),r=new e.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),l=t.map(o(".bookmark"),function(t){return new e.GenomeRegion({from_str:o(t).children(".position").text()})});a="cur"===n?[r]:"bookmarks"===n?l:[r].concat(l),Galaxy.modal.hide(),window.location.href=Galaxy.root+"visualization/sweepster?"+o.param({dataset_id:i.dataset.id,hda_ldda:i.dataset.get("hda_ldda"),regions:JSON.stringify(new s.Collection(a).toJSON())})};Galaxy.modal.show({title:"Visualize tool parameter space and output from different parameter settings?",body:a,buttons:{No:n,Yes:r}})}},R.prototype.action_icons_def[2]],can_draw:function(){return this.dataset&&R.prototype.can_draw.call(this)},build_container_div:function(){return o("").addClass("track").attr("id","track_"+this.id)},set_dataset:function(t){this.dataset=t,this.data_manager.set("dataset",t)},on_resize:function(){this.request_draw({clear_tile_cache:!0})},add_resize_handle:function(){var t=this,e=!1,i=!1,a=o("