workflow-to-galaxy 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +5 -0
- data/README +1 -1
- data/Rakefile +5 -10
- data/bin/workflow_to_galaxy.rb +58 -65
- data/doc/rdoc/CHANGES.html +10 -3
- data/doc/rdoc/Generator.html +49 -46
- data/doc/rdoc/LICENSE.html +3 -3
- data/doc/rdoc/README.html +4 -4
- data/doc/rdoc/WorkflowToGalaxy.html +33 -3
- data/doc/rdoc/WorkflowToGalaxy/GalaxyTool.html +338 -0
- data/doc/rdoc/WorkflowToGalaxy/Workflows.html +155 -0
- data/doc/rdoc/created.rid +6 -7
- data/doc/rdoc/index.html +6 -6
- data/doc/rdoc/lib/workflow-to-galaxy/constants_rb.html +52 -0
- data/doc/rdoc/lib/workflow-to-galaxy/generator_rb.html +7 -4
- data/doc/rdoc/lib/workflow-to-galaxy_rb.html +4 -2
- data/lib/workflow-to-galaxy.rb +4 -2
- data/lib/workflow-to-galaxy/constants.rb +8 -0
- data/lib/workflow-to-galaxy/galaxy.rb +628 -0
- metadata +22 -20
- data/lib/generator.rb +0 -265
- data/lib/workflow-to-galaxy/generator.rb +0 -511
- data/lib/workflow_to_galaxy.rb +0 -65
data/doc/rdoc/created.rid
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
|
2
|
-
lib/
|
3
|
-
lib/workflow-to-galaxy.rb
|
1
|
+
Thu, 13 Oct 2011 12:56:15 +0200
|
2
|
+
lib/workflow-to-galaxy.rb Thu, 13 Oct 2011 12:51:40 +0200
|
3
|
+
lib/workflow-to-galaxy/constants.rb Mon, 10 Oct 2011 14:10:32 +0200
|
4
|
+
lib/workflow-to-galaxy/galaxy.rb Thu, 13 Oct 2011 12:47:28 +0200
|
4
5
|
LICENSE Tue, 26 Jul 2011 16:35:55 +0200
|
5
|
-
|
6
|
-
|
7
|
-
CHANGES Tue, 26 Jul 2011 16:35:55 +0200
|
8
|
-
lib/workflow-to-galaxy/generator.rb Tue, 26 Jul 2011 16:35:55 +0200
|
6
|
+
README Tue, 04 Oct 2011 17:25:08 +0200
|
7
|
+
CHANGES Thu, 13 Oct 2011 12:55:19 +0200
|
data/doc/rdoc/index.html
CHANGED
@@ -29,7 +29,7 @@
|
|
29
29
|
<p>Konstantinos Karasavvas</p>
|
30
30
|
</td></tr><tr><td class="rdoc-term"><p>Gem Version</p></td>
|
31
31
|
<td>
|
32
|
-
<p>0.
|
32
|
+
<p>0.3.0</p>
|
33
33
|
</td></tr><tr><td class="rdoc-term"><p>Contact</p></td>
|
34
34
|
<td>
|
35
35
|
<p><a href="mailto:kostas.karasavvas@nbic.nl">kostas.karasavvas@nbic.nl</a></p>
|
@@ -120,20 +120,20 @@ href="https://trac.nbic.nl/elabfactory/wiki/eGalaxy">trac.nbic.nl/elabfactory/wi
|
|
120
120
|
<h2 id="classes">Classes/Modules</h2>
|
121
121
|
<ul>
|
122
122
|
|
123
|
-
<li class="module"><a href="
|
123
|
+
<li class="module"><a href="WorkflowToGalaxy.html">WorkflowToGalaxy</a></li>
|
124
124
|
|
125
|
-
<li class="class"><a href="
|
125
|
+
<li class="class"><a href="WorkflowToGalaxy/GalaxyTool.html">WorkflowToGalaxy::GalaxyTool</a></li>
|
126
126
|
|
127
|
-
<li class="module"><a href="WorkflowToGalaxy.html">WorkflowToGalaxy</a></li>
|
127
|
+
<li class="module"><a href="WorkflowToGalaxy/Workflows.html">WorkflowToGalaxy::Workflows</a></li>
|
128
128
|
|
129
129
|
</ul>
|
130
130
|
|
131
131
|
<h2 id="methods">Methods</h2>
|
132
132
|
<ul>
|
133
133
|
|
134
|
-
<li><a href="
|
134
|
+
<li><a href="WorkflowToGalaxy/GalaxyTool.html#method-c-new">::new — WorkflowToGalaxy::GalaxyTool</a></li>
|
135
135
|
|
136
|
-
<li><a href="
|
136
|
+
<li><a href="WorkflowToGalaxy/GalaxyTool.html#method-i-generate">#generate — WorkflowToGalaxy::GalaxyTool</a></li>
|
137
137
|
|
138
138
|
</ul>
|
139
139
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
+
|
5
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
6
|
+
<head>
|
7
|
+
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
8
|
+
|
9
|
+
<title>File: constants.rb [workflow-to-galaxy Docs]</title>
|
10
|
+
|
11
|
+
<link type="text/css" media="screen" href="../../rdoc.css" rel="stylesheet" />
|
12
|
+
|
13
|
+
<script src="../../js/jquery.js" type="text/javascript"
|
14
|
+
charset="utf-8"></script>
|
15
|
+
<script src="../../js/thickbox-compressed.js" type="text/javascript"
|
16
|
+
charset="utf-8"></script>
|
17
|
+
<script src="../../js/quicksearch.js" type="text/javascript"
|
18
|
+
charset="utf-8"></script>
|
19
|
+
<script src="../../js/darkfish.js" type="text/javascript"
|
20
|
+
charset="utf-8"></script>
|
21
|
+
</head>
|
22
|
+
|
23
|
+
<body class="file file-popup">
|
24
|
+
<div id="metadata">
|
25
|
+
<dl>
|
26
|
+
<dt class="modified-date">Last Modified</dt>
|
27
|
+
<dd class="modified-date">Mon Oct 10 14:10:32 +0200 2011</dd>
|
28
|
+
|
29
|
+
|
30
|
+
<dt class="requires">Requires</dt>
|
31
|
+
<dd class="requires">
|
32
|
+
<ul>
|
33
|
+
|
34
|
+
</ul>
|
35
|
+
</dd>
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
</dl>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<div id="documentation">
|
43
|
+
|
44
|
+
<div class="description">
|
45
|
+
<h2>Description</h2>
|
46
|
+
|
47
|
+
</div>
|
48
|
+
|
49
|
+
</div>
|
50
|
+
</body>
|
51
|
+
</html>
|
52
|
+
|
@@ -24,13 +24,19 @@
|
|
24
24
|
<div id="metadata">
|
25
25
|
<dl>
|
26
26
|
<dt class="modified-date">Last Modified</dt>
|
27
|
-
<dd class="modified-date">
|
27
|
+
<dd class="modified-date">Thu Oct 13 12:25:01 +0200 2011</dd>
|
28
28
|
|
29
29
|
|
30
30
|
<dt class="requires">Requires</dt>
|
31
31
|
<dd class="requires">
|
32
32
|
<ul>
|
33
33
|
|
34
|
+
<li>myexperiment-rest</li>
|
35
|
+
|
36
|
+
<li>t2flow/model.rb</li>
|
37
|
+
|
38
|
+
<li>t2flow/parser.rb</li>
|
39
|
+
|
34
40
|
</ul>
|
35
41
|
</dd>
|
36
42
|
|
@@ -44,9 +50,6 @@
|
|
44
50
|
<div class="description">
|
45
51
|
<h2>Description</h2>
|
46
52
|
|
47
|
-
<p>The <a href="../../Generator.html">Generator</a> module contains two public
|
48
|
-
methods that generate a Galaxy’s tool XML and script files</p>
|
49
|
-
|
50
53
|
</div>
|
51
54
|
|
52
55
|
</div>
|
@@ -24,14 +24,16 @@
|
|
24
24
|
<div id="metadata">
|
25
25
|
<dl>
|
26
26
|
<dt class="modified-date">Last Modified</dt>
|
27
|
-
<dd class="modified-date">
|
27
|
+
<dd class="modified-date">Thu Oct 13 12:51:40 +0200 2011</dd>
|
28
28
|
|
29
29
|
|
30
30
|
<dt class="requires">Requires</dt>
|
31
31
|
<dd class="requires">
|
32
32
|
<ul>
|
33
33
|
|
34
|
-
<li>workflow-to-galaxy/
|
34
|
+
<li>workflow-to-galaxy/galaxy</li>
|
35
|
+
|
36
|
+
<li>workflow-to-galaxy/constants</li>
|
35
37
|
|
36
38
|
</ul>
|
37
39
|
</dd>
|
data/lib/workflow-to-galaxy.rb
CHANGED
@@ -0,0 +1,628 @@
|
|
1
|
+
require 'myexperiment-rest'
|
2
|
+
require 't2flow/model.rb'
|
3
|
+
require 't2flow/parser.rb'
|
4
|
+
|
5
|
+
|
6
|
+
module WorkflowToGalaxy
|
7
|
+
include MyExperimentREST
|
8
|
+
|
9
|
+
|
10
|
+
#
|
11
|
+
# The _GalaxyTool_ class contains a +generate+ public method that generates the
|
12
|
+
# required files (XML and script) for a Galaxy tool.
|
13
|
+
#
|
14
|
+
class GalaxyTool
|
15
|
+
|
16
|
+
# +config+ contains data needed in relation to what the tool will do and
|
17
|
+
# +wkf_object+ contains the workflow object that will be used to generate
|
18
|
+
# the galaxy tool
|
19
|
+
attr_accessor :wkf_object, :config
|
20
|
+
|
21
|
+
|
22
|
+
# Instantiates a galaxy tool generator.
|
23
|
+
# +config+ is a hash:
|
24
|
+
#
|
25
|
+
# :wkf_source (initial workflow input, see Workflows module)
|
26
|
+
# :params (a hash with the following parameters -- MYEXPERIMENT_TAVERNA2)
|
27
|
+
# :t2_server (the t2 server)
|
28
|
+
# :url (the myexperiment workflow URL)
|
29
|
+
# :xml_out (the file handle for the generated xml -- optional)
|
30
|
+
# :rb_out (the file handle for the generated rb -- optional)
|
31
|
+
#
|
32
|
+
# :params (a hash with the following parameters -- T2FLOW)
|
33
|
+
# :t2flow (the file name and path)
|
34
|
+
# :xml_out (the file handle for the generated xml -- optional)
|
35
|
+
# :rb_out (the file handle for the generated rb -- optional)
|
36
|
+
|
37
|
+
#-
|
38
|
+
# TODO: does initialize appear in rdoc? -- these will go to README as well...
|
39
|
+
def initialize(config)
|
40
|
+
@config = config
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
# private methods
|
46
|
+
private
|
47
|
+
|
48
|
+
# Used to create indentation when generating code
|
49
|
+
def indent(n)
|
50
|
+
ind = ""
|
51
|
+
n.times { ind += " " }
|
52
|
+
ind
|
53
|
+
end
|
54
|
+
|
55
|
+
# Galaxy's XML tool tag
|
56
|
+
def tool_begin_tag(out, name)
|
57
|
+
out.write("<tool id=\"#{name}_id\" name=\"#{name}\">\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
# Galaxy's XML command tag
|
61
|
+
def command_tag(out, t2_workflow, script)
|
62
|
+
out.write indent(1) + "<command interpreter=\"ruby\">\n"
|
63
|
+
out.write indent(2) + script + "\n"
|
64
|
+
|
65
|
+
# inputs
|
66
|
+
t2_workflow.inputs.each do |i|
|
67
|
+
out.write indent(2) + "#if $#{i.name}_source.history_or_textfield == \"textfield\":\n"
|
68
|
+
out.write indent(3) + "false \"$#{i.name}_source.textfield_#{i.name}\"\n"
|
69
|
+
out.write indent(2) + "#else:\n"
|
70
|
+
out.write indent(3) + "true \"$#{i.name}_source.history_#{i.name}\"\n"
|
71
|
+
out.write indent(2) + "#end if\n"
|
72
|
+
end
|
73
|
+
|
74
|
+
# results as zip input
|
75
|
+
out.write indent(2) + "$results_as_zip\n"
|
76
|
+
|
77
|
+
# outputs
|
78
|
+
out.write indent(2)
|
79
|
+
t2_workflow.outputs.each do |o|
|
80
|
+
out.write "$#{o.name} "
|
81
|
+
end
|
82
|
+
|
83
|
+
# result zip output
|
84
|
+
out.write "$result_zip\n"
|
85
|
+
|
86
|
+
out.write indent(1) + "</command>\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Galaxy's XML inputs tag
|
91
|
+
def inputs_tag(out, inputs)
|
92
|
+
out.write indent(1) + "<inputs>\n"
|
93
|
+
if inputs.size >= 1
|
94
|
+
inputs.each do |i|
|
95
|
+
out.write indent(2) + "<conditional name=\"#{i.name}_source\">\n"
|
96
|
+
out.write indent(3) + "<param name=\"history_or_textfield\" type=\"select\" label=\"Select source for #{i.name}\">\n"
|
97
|
+
out.write indent(4) + "<option value=\"history\">From history</option>\n"
|
98
|
+
out.write indent(4) + "<option value=\"textfield\" selected=\"true\">Type manually</option>\n"
|
99
|
+
out.write indent(3) + "</param>\n"
|
100
|
+
out.write indent(3) + "<when value=\"history\">\n"
|
101
|
+
out.write indent(4) + "<param name=\"history_#{i.name}\" type=\"data\" label=\"Select #{i.name}\"/>\n"
|
102
|
+
out.write indent(3) + "</when>\n"
|
103
|
+
out.write indent(3) + "<when value=\"textfield\">\n"
|
104
|
+
out.write indent(4) + "<param name=\"textfield_#{i.name}\" type=\"text\" area=\"True\" size=\"2x50\" "
|
105
|
+
if i.examples.size >= 1
|
106
|
+
# escape double quotes characters for galaxy's xml file
|
107
|
+
ex = i.examples[0].to_s.gsub('"', '"')
|
108
|
+
# convert newlines to HTML newlines to display in textareas inputs
|
109
|
+
ex = ex.gsub(/[\n]/, '
')
|
110
|
+
out.write "value=\"#{ex}\" "
|
111
|
+
end
|
112
|
+
out.write "label=\"Enter #{i.name}\"/>\n"
|
113
|
+
out.write indent(3) + "</when>\n"
|
114
|
+
out.write indent(2) + "</conditional>\n"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
out.write indent(2) + "<param name=\"input\" type=\"select\" display=\"radio\" size=\"250\" label=\"This workflow has no inputs\" />\n"
|
118
|
+
end
|
119
|
+
|
120
|
+
# result as zip input
|
121
|
+
out.write indent(2) + "<param name=\"results_as_zip\" type=\"select\" label=\"Would you also like the raw results as a zip file\">\n"
|
122
|
+
out.write indent(3) + "<option value=\"yes\">Yes</option>\n"
|
123
|
+
out.write indent(3) + "<option value=\"no\" selected=\"true\">No</option>\n"
|
124
|
+
out.write indent(2) + "</param>\n"
|
125
|
+
|
126
|
+
out.write indent(1) + "</inputs>\n"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Galaxy's XML outputs tag
|
130
|
+
def outputs_tag(out, outputs)
|
131
|
+
out.write indent(1) + "<outputs>\n"
|
132
|
+
outputs.each do |o|
|
133
|
+
out.write indent(2) + "<data format=\"tabular\" name=\"#{o.name}\" label=\"#{o.name}\"/>\n"
|
134
|
+
end
|
135
|
+
|
136
|
+
# result zip output
|
137
|
+
out.write indent(2) + "<data format=\"zip\" name=\"result_zip\" label=\"Compressed Results (zip)\">\n"
|
138
|
+
out.write indent(3) + "<filter>results_as_zip == \"yes\"</filter>\n"
|
139
|
+
out.write indent(2) + "</data>\n"
|
140
|
+
|
141
|
+
out.write indent(1) + "</outputs>\n"
|
142
|
+
end
|
143
|
+
|
144
|
+
# Galaxy's XML help tag
|
145
|
+
def help_tag(out, t2_workflow)
|
146
|
+
out.write indent(1) + "<help>\n"
|
147
|
+
|
148
|
+
if t2_workflow.description
|
149
|
+
out.write "**What it does**\n\n"
|
150
|
+
|
151
|
+
description = t2_workflow.description + "\n\n"
|
152
|
+
|
153
|
+
# Sometimes the workflow description contains HTML tags that are not allowed
|
154
|
+
# in Galaxy's xml interface specification and thus are removed! Same for
|
155
|
+
# HTML entities!
|
156
|
+
# TODO go through tags and find Galaxy's equivalent to include
|
157
|
+
description.gsub!(/<.*?>|&.*?;/, '')
|
158
|
+
|
159
|
+
# To remove ^M (cntl-v + cntl-m) characters that DOS files might have
|
160
|
+
description.gsub!(/\r/, '')
|
161
|
+
|
162
|
+
# TODO that works as a literal too but font changes to courier!
|
163
|
+
#out.write "::\n\n" # Start Galaxy's literal block to ignore indendation
|
164
|
+
|
165
|
+
# remove indendation from all description lines since Galaxy is confused by it
|
166
|
+
description.split(/[\n]/).each { |l| out.write "#{l.gsub(/^\s+/, '')}\n" }
|
167
|
+
|
168
|
+
# endline makes the following be parsed as a Galaxy GUI construct
|
169
|
+
out.write "\n"
|
170
|
+
end
|
171
|
+
|
172
|
+
# if at least one input add it to tool's UI help description
|
173
|
+
if t2_workflow.inputs.size >= 1
|
174
|
+
out.write "-----\n\n"
|
175
|
+
out.write "**Inputs**\n\n"
|
176
|
+
t2_workflow.inputs.each do |i|
|
177
|
+
out.write "- **#{i.name}** "
|
178
|
+
if i.descriptions.size >= 1
|
179
|
+
i.descriptions.each do |desc|
|
180
|
+
out.write desc.to_s + " "
|
181
|
+
end
|
182
|
+
end
|
183
|
+
if i.examples.size >= 1
|
184
|
+
out.write "Examples include:\n\n"
|
185
|
+
i.examples.each do |ex|
|
186
|
+
# some examples have a newline between them that breaks Galaxy's GUI
|
187
|
+
# so we substitute it with ' '
|
188
|
+
#out.write " - " + ex.to_s.gsub(/[\n]/, ' ') + "\n"
|
189
|
+
|
190
|
+
# We could substitute them with with 
 that works for HTML (e.g. wkf 1180)
|
191
|
+
# But if an example input is truly multiline then input descr. will
|
192
|
+
# display them all as separate inputs...
|
193
|
+
out.write " - " + ex.to_s.gsub(/[\n]/, '
 - ') + "\n"
|
194
|
+
|
195
|
+
# display example inputs as verbatim/literal so it is not our responsibility!!
|
196
|
+
# add indendation after each newline to specify the literal block
|
197
|
+
# TODO this looks ugly if we don't remove all the bullet points!
|
198
|
+
#out.write "::\n\n " + ex.to_s.gsub(/\n/, '
 ') + "\n"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
out.write "\n"
|
202
|
+
end
|
203
|
+
out.write "\n"
|
204
|
+
end
|
205
|
+
|
206
|
+
# if at least one output add it to tool's UI help description
|
207
|
+
if t2_workflow.outputs.size >= 1
|
208
|
+
out.write "-----\n\n"
|
209
|
+
out.write "**Outputs**\n\n"
|
210
|
+
t2_workflow.outputs.each do |o|
|
211
|
+
out.write "- **#{o.name}** "
|
212
|
+
if o.descriptions.size >= 1
|
213
|
+
o.descriptions.each do |desc|
|
214
|
+
out.write desc.to_s + " "
|
215
|
+
end
|
216
|
+
end
|
217
|
+
if o.examples.size >= 1
|
218
|
+
out.write "Examples include:\n\n"
|
219
|
+
o.examples.each do |ex|
|
220
|
+
out.write " - " + ex.to_s + "\n"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
out.write "\n"
|
224
|
+
end
|
225
|
+
out.write "\n"
|
226
|
+
end
|
227
|
+
|
228
|
+
out.write "-----\n\n"
|
229
|
+
out.write ".. class:: warningmark\n\n"
|
230
|
+
out.write "**Please note that some workflows are not up-to-date or have dependencies** " <<
|
231
|
+
"that cannot be met by the specific Taverna server that you specified during " <<
|
232
|
+
"generation of this tool. You can make sure that the workflow is valid " <<
|
233
|
+
"by running it in the Taverna Workbench first to confirm that it works " <<
|
234
|
+
"before running it via Galaxy.\n\n"
|
235
|
+
|
236
|
+
if @config[:wkf_source] == Workflows::MYEXPERIMENT_TAVERNA2
|
237
|
+
out.write "-----\n\n"
|
238
|
+
out.write ".. class:: warningmark\n\n"
|
239
|
+
out.write "**Please note that there might be some repetitions in the workflow description** " <<
|
240
|
+
"in some of the generated workflows. This is due to a backwards compatibility " <<
|
241
|
+
"issue on the myExperiment repository which keeps the old descriptions to make " <<
|
242
|
+
"sure that no information is lost.\n\n"
|
243
|
+
|
244
|
+
out.write "-----\n\n"
|
245
|
+
out.write ".. class:: infomark\n\n"
|
246
|
+
out.write "**For more information on that workflow please visit** #{t2_workflow.content_uri.gsub(/(.*workflows\/\d+)[\/.].*/, '\1')}.\n\n"
|
247
|
+
end
|
248
|
+
|
249
|
+
out.write indent(1) + "</help>\n"
|
250
|
+
end
|
251
|
+
|
252
|
+
# Galaxy's XML tool tag close
|
253
|
+
def tool_end_tag(out)
|
254
|
+
out.write("</tool>\n")
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
# Galaxy's script preample
|
260
|
+
def script_preample(out)
|
261
|
+
out.write("#!/usr/bin/env ruby\n\n")
|
262
|
+
|
263
|
+
out.write("# This script can be tested without Galaxy. You can run from the shell as follows:\n#\n")
|
264
|
+
out.write("# $ script_name.rb <input1> true|false <input2> true|false yes|no <output1> <output2>\n#\n")
|
265
|
+
out.write("# After each input value a boolean specifies if the value is literal (false) or if\n")
|
266
|
+
out.write("# it specifies a file name to read as input.\n#\n")
|
267
|
+
out.write("# After all workflow inputs a yes or no input specifies if we also want our results zipped.\n#\n")
|
268
|
+
out.write("# Finally, all the output files follow. Note that if you selected to also get a zip\n")
|
269
|
+
out.write("# then you need to specify an additional output in the end after the normal workflow\n")
|
270
|
+
out.write("# outputs.\n\n")
|
271
|
+
|
272
|
+
out.write("require 'rubygems'\n")
|
273
|
+
out.write("require 't2-server'\n")
|
274
|
+
out.write("require 'open-uri'\n")
|
275
|
+
out.write("require 'zip/zipfilesystem'\n\n")
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
# Galaxy's script utility methods
|
280
|
+
# TODO: use ruby's flatten instead of our own !!!
|
281
|
+
def script_util_methods(out)
|
282
|
+
|
283
|
+
out.write <<'UTIL_METHODS'
|
284
|
+
|
285
|
+
# sends the zip file to specified output
|
286
|
+
def output_zip_file(uuid, zip_out)
|
287
|
+
File.open("/tmp/#{uuid}.zip") do |zip|
|
288
|
+
while data = zip.read(4096)
|
289
|
+
zip_out.write data
|
290
|
+
end
|
291
|
+
end
|
292
|
+
File.delete("/tmp/#{uuid}.zip")
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
#
|
297
|
+
# replicates the directory result structure as constructed by the
|
298
|
+
# taverna server and recreates it in a zip File
|
299
|
+
#
|
300
|
+
def add_to_zip_file(output_dir, data_lists, zip_out)
|
301
|
+
zip_out.dir.mkdir("#{output_dir}")
|
302
|
+
data_lists.each_with_index do |item, index|
|
303
|
+
if item.instance_of? Array
|
304
|
+
add_to_zip_file("#{output_dir}/#{index+1}", item, zip_out)
|
305
|
+
else
|
306
|
+
zip_out.file.open("#{output_dir}/#{index+1}", "w") { |f| f.puts item }
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
# method that flattens the list of list of list ... result of get_output
|
313
|
+
def print_flattened_result(out, data_lists)
|
314
|
+
data_lists.each do |l|
|
315
|
+
if l.instance_of? Array
|
316
|
+
print_flattened_result(out, l)
|
317
|
+
else
|
318
|
+
out.puts l
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
|
324
|
+
#
|
325
|
+
# Method that acquires all the results of the specified output directory.
|
326
|
+
# If valid zip File is passed it also accumulates results as a zip file.
|
327
|
+
#
|
328
|
+
def get_outputs(run, refs, outfile, dir, zip_out=nil)
|
329
|
+
data_lists = run.get_output(dir, refs)
|
330
|
+
print_flattened_result(outfile, data_lists)
|
331
|
+
if zip_out
|
332
|
+
add_to_zip_file(dir, data_lists, zip_out)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
#
|
338
|
+
# Sanitize all special characters in UI inputs that Galaxy substitutes for
|
339
|
+
# security reasons. This methods turns them back to their original values before
|
340
|
+
# using them (i.e. sending them to the taverna server
|
341
|
+
# NB: note that double quote is sanitized to "'" that is because the double code
|
342
|
+
# confuses the Taverna server ruby library. Apparently, this is not trivial
|
343
|
+
# to fix.
|
344
|
+
#
|
345
|
+
def sanitize(string)
|
346
|
+
string.gsub(/(__sq__|__dq__|__at__|__cr__|__cn__|__tc__|__gt__|__lt__|__ob__|__cb__|__oc__|__cc__)/) do
|
347
|
+
if $1 == '__sq__'
|
348
|
+
"'"
|
349
|
+
elsif $1 == '__dq__'
|
350
|
+
"'"
|
351
|
+
elsif $1 == '__cr__'
|
352
|
+
"\r"
|
353
|
+
elsif $1 == '__cn__'
|
354
|
+
"\n"
|
355
|
+
elsif $1 == '__tc__'
|
356
|
+
"\t"
|
357
|
+
elsif $1 == '__gt__'
|
358
|
+
'>'
|
359
|
+
elsif $1 == '__lt__'
|
360
|
+
'<'
|
361
|
+
elsif $1 == '__ob__'
|
362
|
+
'['
|
363
|
+
elsif $1 == '__cb__'
|
364
|
+
']'
|
365
|
+
elsif $1 == '__oc__'
|
366
|
+
'{'
|
367
|
+
elsif $1 == '__cc__'
|
368
|
+
'}'
|
369
|
+
else
|
370
|
+
'@'
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
#
|
376
|
+
# Deletes last new line of file if it exists! It is needed for t2 workflows that
|
377
|
+
# do not sanitize properly, i.e. via a user-provided beanshell script
|
378
|
+
#
|
379
|
+
def chomp_last_newline(file)
|
380
|
+
|
381
|
+
if File.file?(file) and File.size(file) > 1
|
382
|
+
f = open(file, "rb+")
|
383
|
+
f.seek(-1, File::SEEK_END)
|
384
|
+
f.truncate(File.size(file) - 1) if f.read(1) == "\n"
|
385
|
+
f.close
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
|
390
|
+
|
391
|
+
UTIL_METHODS
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
# Galaxy's script taverna 2 run
|
396
|
+
def script_create_t2_run(out, wkf, t2_uri)
|
397
|
+
if @config[:wkf_source] == Workflows::MYEXPERIMENT_TAVERNA2
|
398
|
+
out.write "# use the uri reference to download the workflow locally\n"
|
399
|
+
out.write "wkf_file = URI.parse('#{wkf.content_uri}')\n"
|
400
|
+
out.write "in_wkf = open(wkf_file)\n"
|
401
|
+
else # Workflows::T2FLOW
|
402
|
+
out.write "# uri contains local t2flow file\n"
|
403
|
+
out.write "in_wkf = open('#{wkf.content_uri}')\n"
|
404
|
+
end
|
405
|
+
|
406
|
+
out.write <<CREATE_T2_RUN
|
407
|
+
|
408
|
+
wkf = in_wkf.read()
|
409
|
+
|
410
|
+
# create run
|
411
|
+
begin
|
412
|
+
run = T2Server::Run.create('#{t2_uri}', wkf)
|
413
|
+
rescue T2Server::T2ServerError => e
|
414
|
+
exit 1
|
415
|
+
end
|
416
|
+
|
417
|
+
CREATE_T2_RUN
|
418
|
+
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
# Galaxy's script input handling
|
423
|
+
def script_init_inputs(out, t2_workflow)
|
424
|
+
out.write "#\n"
|
425
|
+
out.write "# Get input arguments -- for each input a boolean specifies if it's from history\n"
|
426
|
+
out.write "# thus, for each t2_workflow input we have two arguments in the script!\n"
|
427
|
+
out.write "#\n"
|
428
|
+
t2_workflow.inputs.each_with_index do |input, i|
|
429
|
+
i_name = input.name.to_s
|
430
|
+
out.write "#{i_name}_from_history = ARGV[#{i*2}].chomp\n"
|
431
|
+
out.write "#{i_name}_tmp = ARGV[#{i*2+1}].chomp\n"
|
432
|
+
out.write "if #{i_name}_from_history == \"true\"\n"
|
433
|
+
out.write " chomp_last_newline(#{i_name}_tmp)\n"
|
434
|
+
out.write " run.upload_input_file('#{i_name}', #{i_name}_tmp)\n"
|
435
|
+
out.write "else\n"
|
436
|
+
out.write " run.set_input('#{i_name}', sanitize(#{i_name}_tmp))\n"
|
437
|
+
out.write "end\n"
|
438
|
+
end
|
439
|
+
|
440
|
+
# add code to handle results_as_zip input, i.e. create zip file
|
441
|
+
out.write "\n# get results_as_zip input and open zip file if appropriate\n"
|
442
|
+
# get argument index after workflow inputs
|
443
|
+
zip_index = t2_workflow.inputs.size * 2
|
444
|
+
out.write "zipped = ARGV[#{zip_index}].chomp == \"yes\"\n"
|
445
|
+
out.write 'zip_out = Zip::ZipFile.open("/tmp/#{run.uuid}.zip", Zip::ZipFile::CREATE) if zipped' + "\n"
|
446
|
+
|
447
|
+
end
|
448
|
+
|
449
|
+
|
450
|
+
# Galaxy's script starting taverna run
|
451
|
+
def script_start_run(out)
|
452
|
+
out.write <<START_RUN
|
453
|
+
|
454
|
+
|
455
|
+
# start run and wait until it is finished
|
456
|
+
run.start
|
457
|
+
run.wait(:progress => true)
|
458
|
+
|
459
|
+
START_RUN
|
460
|
+
end
|
461
|
+
|
462
|
+
|
463
|
+
# Galaxy's script output handling
|
464
|
+
def script_get_outputs(out, t2_workflow)
|
465
|
+
# outputs start after all inputs plus the results_as_zip input
|
466
|
+
outputs_start_index = t2_workflow.inputs.size * 2 + 1
|
467
|
+
outputs_end_index = outputs_start_index + t2_workflow.outputs.size - 1
|
468
|
+
out.write "# get output arguments and associated them with a file\n"
|
469
|
+
outputs_start_index.upto(outputs_end_index) do |o|
|
470
|
+
out.write "output#{o} = File.open(ARGV[#{o}], \"w\")\n"
|
471
|
+
out.write "begin\n"
|
472
|
+
out.write " get_outputs(run, false, output#{o}, '" + t2_workflow.outputs[o - outputs_start_index].name.to_s + "', zip_out)\n"
|
473
|
+
out.write "rescue Exception => err\n"
|
474
|
+
out.write " get_outputs(run, false, output#{o}, '" + t2_workflow.outputs[o - outputs_start_index].name.to_s + ".error', zip_out)\n"
|
475
|
+
out.write "ensure\n"
|
476
|
+
out.write " output#{o}.close\n"
|
477
|
+
out.write "end\n"
|
478
|
+
end
|
479
|
+
|
480
|
+
# close zip file if created when dealing with the inputs
|
481
|
+
#--
|
482
|
+
# ideally that would semantically belong to a separate method
|
483
|
+
out.write "\n# close zip_out (the newly created zip file) if opened\n"
|
484
|
+
out.write "zip_out.close if zip_out\n"
|
485
|
+
|
486
|
+
# dealing with zip output here -- zip arg index is outputs_end_index (last
|
487
|
+
# output) plus 1
|
488
|
+
out.write "\n# open galaxy zip output and write zip file\n"
|
489
|
+
out.write "if zipped\n"
|
490
|
+
out.write " galaxy_zip_out = File.open(ARGV[#{outputs_end_index+1}], \"w\")\n"
|
491
|
+
out.write " output_zip_file(run.uuid, galaxy_zip_out)\n"
|
492
|
+
out.write " galaxy_zip_out.close\n"
|
493
|
+
out.write "end\n"
|
494
|
+
|
495
|
+
end
|
496
|
+
|
497
|
+
|
498
|
+
# Galaxy's script cleaning taverna run
|
499
|
+
def script_finish_run(out)
|
500
|
+
out.write "\n# delete run\n"
|
501
|
+
out.write "run.delete\n"
|
502
|
+
end
|
503
|
+
|
504
|
+
|
505
|
+
|
506
|
+
# Generates the Galaxy tool's xml file responsible for the UI.
|
507
|
+
# TODO: maybe clean arguments -- only xml_out is needed to be passed
|
508
|
+
def generate_xml(t2_workflow, xml_out)
|
509
|
+
tool_begin_tag(xml_out, xml_out.path.match('([^\/]+)\..*$')[1])
|
510
|
+
command_tag(xml_out, t2_workflow, xml_out.path.match('([^\/]+)\..*$')[1] + '.rb')
|
511
|
+
inputs_tag(xml_out, t2_workflow.inputs)
|
512
|
+
outputs_tag(xml_out, t2_workflow.outputs)
|
513
|
+
help_tag(xml_out, t2_workflow)
|
514
|
+
tool_end_tag(xml_out)
|
515
|
+
end
|
516
|
+
|
517
|
+
|
518
|
+
# Generates the Galaxy tool's script file responsible for talking to the
|
519
|
+
# taverna server
|
520
|
+
# TODO: maybe clean arguments -- only xml_out is needed to be passed
|
521
|
+
def generate_rb(t2_workflow, script_out, t2_server)
|
522
|
+
script_preample(script_out)
|
523
|
+
script_util_methods(script_out)
|
524
|
+
script_create_t2_run(script_out, t2_workflow, t2_server)
|
525
|
+
script_init_inputs(script_out, t2_workflow)
|
526
|
+
script_start_run(script_out)
|
527
|
+
script_get_outputs(script_out, t2_workflow)
|
528
|
+
script_finish_run(script_out)
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
# Populates and returns a _MyExperimentWorkflow_ object (same as in
|
533
|
+
# myexperiment-rest) from a local t2flow file.
|
534
|
+
def populate_taverna_workflow_from_t2flow(t2flow)
|
535
|
+
t2flow_file = File.new(t2flow, "r")
|
536
|
+
parsed_t2flow = T2Flow::Parser.new.parse(t2flow_file)
|
537
|
+
|
538
|
+
wkf_title = parsed_t2flow.name
|
539
|
+
wkf_descr = parsed_t2flow.main.annotations.descriptions[0] # gets only the first
|
540
|
+
wkf_uploader_uri = parsed_t2flow.main.annotations.authors[0]
|
541
|
+
wkf_sources = []
|
542
|
+
parsed_t2flow.main.sources.each do |s|
|
543
|
+
wkf_sources << MyExperimentIOData.new(:name => s.name,
|
544
|
+
:descriptions => s.descriptions ? CGI.escapeHTML(s.descriptions.to_s) : [],
|
545
|
+
:examples => s.example_values ? s.example_values : [])
|
546
|
+
end
|
547
|
+
wkf_sinks = []
|
548
|
+
parsed_t2flow.main.sinks.each do |s|
|
549
|
+
wkf_sinks << MyExperimentIOData.new(:name => s.name,
|
550
|
+
:descriptions => s.descriptions ? CGI.escapeHTML(s.descriptions.to_s) : [],
|
551
|
+
:examples => s.example_values ? s.example_values : [])
|
552
|
+
end
|
553
|
+
|
554
|
+
workflow = MyExperimentWorkflow.new(:content_uri => t2flow,
|
555
|
+
:title => wkf_title,
|
556
|
+
:description => wkf_descr,
|
557
|
+
:inputs => wkf_sources,
|
558
|
+
:outputs => wkf_sinks,
|
559
|
+
:uploader_uri => wkf_uploader_uri)
|
560
|
+
|
561
|
+
end
|
562
|
+
|
563
|
+
|
564
|
+
|
565
|
+
# public methods from here onwards
|
566
|
+
public
|
567
|
+
|
568
|
+
#
|
569
|
+
# Generates the two files needed for a Galaxy tool: a configuration
|
570
|
+
# file (XML) and a processing file (in our case a ruby script)
|
571
|
+
#
|
572
|
+
# :call-seq:
|
573
|
+
# GalaxyTool.generate() -> nil
|
574
|
+
#
|
575
|
+
def generate
|
576
|
+
|
577
|
+
# check the type of workflow source and acquire the appropriate data
|
578
|
+
if(config[:wkf_source] == Workflows::MYEXPERIMENT_TAVERNA2)
|
579
|
+
|
580
|
+
# TODO: check and add auth stuff -- even more unsafe with session cookies
|
581
|
+
# since the myexp username/passwd will be saved in the galaxy ruby script
|
582
|
+
# for all to see...
|
583
|
+
|
584
|
+
begin
|
585
|
+
# Get workflow data from myexperiment -- a _MyExperimentWorkflow_ object is returned
|
586
|
+
@wkf_object = MyExperimentREST::Workflow.from_uri(@config[:params][:url])
|
587
|
+
rescue Exception => e
|
588
|
+
raise "Problem acquiring workflow data from myExperiment!\n" + e
|
589
|
+
end
|
590
|
+
|
591
|
+
elsif(config[:wkf_source] == Workflows::T2FLOW)
|
592
|
+
|
593
|
+
begin
|
594
|
+
# Get workflow data from t2flow file -- a _MyExperimentWorkflow_ object is returned
|
595
|
+
@wkf_object = populate_taverna_workflow_from_t2flow(@config[:params][:t2flow])
|
596
|
+
rescue Exception => e
|
597
|
+
raise "Problem acquiring workflow data from t2flow file!\n" + e
|
598
|
+
end
|
599
|
+
|
600
|
+
else
|
601
|
+
raise "No such workflow source supported!"
|
602
|
+
end
|
603
|
+
|
604
|
+
# if an xml_out file handler was not given provide one with the title as the value
|
605
|
+
if @config[:params][:xml_out]
|
606
|
+
generate_xml(@wkf_object, @config[:params][:xml_out])
|
607
|
+
else
|
608
|
+
xml_out = open(@wkf_object.title + ".xml", "w")
|
609
|
+
generate_xml(@wkf_object, xml_out)
|
610
|
+
xml_out.close
|
611
|
+
end
|
612
|
+
|
613
|
+
# if an rb_out file handler was not given provide one with the title as the value
|
614
|
+
if @config[:params][:rb_out]
|
615
|
+
generate_rb(@wkf_object, @config[:params][:rb_out], @config[:params][:t2_server])
|
616
|
+
else
|
617
|
+
rb_out = open(@wkf_object.title + ".rb", "w")
|
618
|
+
generate_rb(@wkf_object, rb_out, @config[:params][:t2_server])
|
619
|
+
rb_out.close
|
620
|
+
end
|
621
|
+
|
622
|
+
|
623
|
+
end
|
624
|
+
|
625
|
+
|
626
|
+
end # class GalaxyTool
|
627
|
+
|
628
|
+
end # module
|