workflow-to-galaxy 0.2.7

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.
@@ -0,0 +1,108 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>File: workflow-to-galaxy.rb</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="fileHeader">
50
+ <h1>workflow-to-galaxy.rb</h1>
51
+ <table class="header-table">
52
+ <tr class="top-aligned-row">
53
+ <td><strong>Path:</strong></td>
54
+ <td>lib/workflow-to-galaxy.rb
55
+ </td>
56
+ </tr>
57
+ <tr class="top-aligned-row">
58
+ <td><strong>Last Update:</strong></td>
59
+ <td>Mon Dec 13 15:22:40 +0100 2010</td>
60
+ </tr>
61
+ </table>
62
+ </div>
63
+ <!-- banner header -->
64
+
65
+ <div id="bodyContent">
66
+
67
+
68
+
69
+ <div id="contextContent">
70
+
71
+
72
+ <div id="requires-list">
73
+ <h3 class="section-bar">Required files</h3>
74
+
75
+ <div class="name-list">
76
+ workflow-to-galaxy/generator&nbsp;&nbsp;
77
+ </div>
78
+ </div>
79
+
80
+ </div>
81
+
82
+
83
+ </div>
84
+
85
+
86
+ <!-- if includes -->
87
+
88
+ <div id="section">
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+ <!-- if method_list -->
98
+
99
+
100
+ </div>
101
+
102
+
103
+ <div id="validator-badges">
104
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
105
+ </div>
106
+
107
+ </body>
108
+ </html>
@@ -0,0 +1,28 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Classes
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Classes</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Classes</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/Generator.html">Generator</a><br />
24
+ <a href="classes/WorkflowToGalaxy.html">WorkflowToGalaxy</a><br />
25
+ </div>
26
+ </div>
27
+ </body>
28
+ </html>
@@ -0,0 +1,30 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Files
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Files</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Files</h1>
22
+ <div id="index-entries">
23
+ <a href="files/LICENSE.html">LICENSE</a><br />
24
+ <a href="files/README.html">README</a><br />
25
+ <a href="files/lib/workflow-to-galaxy_rb.html">lib/workflow-to-galaxy.rb</a><br />
26
+ <a href="files/lib/workflow-to-galaxy/generator_rb.html">lib/workflow-to-galaxy/generator.rb</a><br />
27
+ </div>
28
+ </div>
29
+ </body>
30
+ </html>
@@ -0,0 +1,28 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Methods
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Methods</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Methods</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/Generator.html#M000002">generate_script (Generator)</a><br />
24
+ <a href="classes/Generator.html#M000001">generate_xml (Generator)</a><br />
25
+ </div>
26
+ </div>
27
+ </body>
28
+ </html>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ workflow-to-galaxy Docs
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>workflow-to-galaxy Docs</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/README.html" name="docwin" />
23
+ </frameset>
24
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,5 @@
1
+ require 'workflow-to-galaxy/generator'
2
+
3
+ module WorkflowToGalaxy
4
+
5
+ end
@@ -0,0 +1,497 @@
1
+ #
2
+ # The Generator module contains two public methods that generate a Galaxy's tool
3
+ # XML and script files
4
+ #
5
+ module Generator
6
+
7
+ # private methods
8
+ private
9
+
10
+ # Used to create indentation when generating code
11
+ def indent(n)
12
+ ind = ""
13
+ n.times { ind += " " }
14
+ ind
15
+ end
16
+
17
+ # Galaxy's XML tool tag
18
+ def tool_begin_tag(out, name)
19
+ out.write("<tool id=\"#{name}_id\" name=\"#{name}\">\n")
20
+ end
21
+
22
+ # Galaxy's XML command tag
23
+ def command_tag(out, t2_workflow, script)
24
+ out.write indent(1) + "<command interpreter=\"ruby\">\n"
25
+ out.write indent(2) + script + "\n"
26
+
27
+ # inputs
28
+ t2_workflow.inputs.each do |i|
29
+ out.write indent(2) + "#if $#{i.name}_source.history_or_textfield == \"textfield\":\n"
30
+ out.write indent(3) + "false \"$#{i.name}_source.textfield_#{i.name}\"\n"
31
+ out.write indent(2) + "#else:\n"
32
+ out.write indent(3) + "true \"$#{i.name}_source.history_#{i.name}\"\n"
33
+ out.write indent(2) + "#end if\n"
34
+ end
35
+
36
+ # results as zip input
37
+ out.write indent(2) + "$results_as_zip\n"
38
+
39
+ # outputs
40
+ out.write indent(2)
41
+ t2_workflow.outputs.each do |o|
42
+ out.write "$#{o.name} "
43
+ end
44
+
45
+ # result zip output
46
+ out.write "$result_zip\n"
47
+
48
+ out.write indent(1) + "</command>\n"
49
+ end
50
+
51
+
52
+ # Galaxy's XML inputs tag
53
+ def inputs_tag(out, inputs)
54
+ out.write indent(1) + "<inputs>\n"
55
+ if inputs.size >= 1
56
+ inputs.each do |i|
57
+ out.write indent(2) + "<conditional name=\"#{i.name}_source\">\n"
58
+ out.write indent(3) + "<param name=\"history_or_textfield\" type=\"select\" label=\"Select source for #{i.name}\">\n"
59
+ out.write indent(4) + "<option value=\"history\">From history</option>\n"
60
+ out.write indent(4) + "<option value=\"textfield\" selected=\"true\">Type manually</option>\n"
61
+ out.write indent(3) + "</param>\n"
62
+ out.write indent(3) + "<when value=\"history\">\n"
63
+ out.write indent(4) + "<param name=\"history_#{i.name}\" type=\"data\" label=\"Select #{i.name}\"/>\n"
64
+ out.write indent(3) + "</when>\n"
65
+ out.write indent(3) + "<when value=\"textfield\">\n"
66
+ out.write indent(4) + "<param name=\"textfield_#{i.name}\" type=\"text\" area=\"True\" size=\"2x50\" "
67
+ if i.examples.size >= 1
68
+ # escape double quotes characters for galaxy's xml file
69
+ ex = i.examples[0].to_s.gsub('"', '&quot;')
70
+ # convert newlines to HTML newlines to display in textareas inputs
71
+ ex = ex.gsub(/[\n]/, '&#xA;')
72
+ out.write "value=\"#{ex}\" "
73
+ end
74
+ out.write "label=\"Enter #{i.name}\"/>\n"
75
+ out.write indent(3) + "</when>\n"
76
+ out.write indent(2) + "</conditional>\n"
77
+ end
78
+ else
79
+ out.write indent(2) + "<param name=\"input\" type=\"select\" display=\"radio\" size=\"250\" label=\"This workflow has no inputs\" />\n"
80
+ end
81
+
82
+ # result as zip input
83
+ out.write indent(2) + "<param name=\"results_as_zip\" type=\"select\" label=\"Would you also like the raw results as a zip file\">\n"
84
+ out.write indent(3) + "<option value=\"yes\">Yes</option>\n"
85
+ out.write indent(3) + "<option value=\"no\" selected=\"true\">No</option>\n"
86
+ out.write indent(2) + "</param>\n"
87
+
88
+ out.write indent(1) + "</inputs>\n"
89
+ end
90
+
91
+ # Galaxy's XML outputs tag
92
+ def outputs_tag(out, outputs)
93
+ out.write indent(1) + "<outputs>\n"
94
+ outputs.each do |o|
95
+ out.write indent(2) + "<data format=\"tabular\" name=\"#{o.name}\" label=\"#{o.name}\"/>\n"
96
+ end
97
+
98
+ # result zip output
99
+ out.write indent(2) + "<data format=\"zip\" name=\"result_zip\" label=\"Compressed Results (zip)\">\n"
100
+ out.write indent(3) + "<filter>results_as_zip == \"yes\"</filter>\n"
101
+ out.write indent(2) + "</data>\n"
102
+
103
+ out.write indent(1) + "</outputs>\n"
104
+ end
105
+
106
+ # Galaxy's XML help tag
107
+ def help_tag(out, t2_workflow)
108
+ out.write indent(1) + "<help>\n"
109
+ out.write "**What it does**\n\n"
110
+
111
+ description = t2_workflow.description + "\n\n"
112
+
113
+ # Sometimes the workflow description contains HTML tags that are not allowed
114
+ # in Galaxy's xml interface specification and thus are removed! Same for
115
+ # HTML entities!
116
+ # TODO go through tags and find Galaxy's equivalent to include
117
+ description.gsub!(/<.*?>|&.*?;/, '')
118
+
119
+ # To remove ^M (cntl-v + cntl-m) characters that DOS files might have
120
+ description.gsub!(/\r/, '')
121
+
122
+ # TODO that works as a literal too but font changes to courier!
123
+ #out.write "::\n\n" # Start Galaxy's literal block to ignore indendation
124
+
125
+ # remove indendation from all description lines since Galaxy is confused by it
126
+ description.split(/[\n]/).each { |l| out.write "#{l.gsub(/^\s+/, '')}\n" }
127
+
128
+ # endline makes the following be parsed as a Galaxy GUI construct
129
+ out.write "\n"
130
+
131
+ # if at least one input add it to tool's UI help description
132
+ if t2_workflow.inputs.size >= 1
133
+ out.write "-----\n\n"
134
+ out.write "**Inputs**\n\n"
135
+ t2_workflow.inputs.each do |i|
136
+ out.write "- **#{i.name}** "
137
+ if i.descriptions.size >= 1
138
+ i.descriptions.each do |desc|
139
+ out.write desc.to_s + " "
140
+ end
141
+ end
142
+ if i.examples.size >= 1
143
+ out.write "Examples include:\n\n"
144
+ i.examples.each do |ex|
145
+ # some examples have a newline between them that breaks Galaxy's GUI
146
+ # so we substitute it with ' '
147
+ #out.write " - " + ex.to_s.gsub(/[\n]/, ' ') + "\n"
148
+
149
+ # We could substitute them with with &#xA; that works for HTML (e.g. wkf 1180)
150
+ # But if an example input is truly multiline then input descr. will
151
+ # display them all as separate inputs...
152
+ out.write " - " + ex.to_s.gsub(/[\n]/, '&#xA; - ') + "\n"
153
+
154
+ # display example inputs as verbatim/literal so it is not our responsibility!!
155
+ # add indendation after each newline to specify the literal block
156
+ # TODO this looks ugly if we don't remove all the bullet points!
157
+ #out.write "::\n\n " + ex.to_s.gsub(/\n/, '&#xA; ') + "\n"
158
+ end
159
+ end
160
+ out.write "\n"
161
+ end
162
+ out.write "\n"
163
+ end
164
+
165
+ # if at least one output add it to tool's UI help description
166
+ if t2_workflow.outputs.size >= 1
167
+ out.write "-----\n\n"
168
+ out.write "**Outputs**\n\n"
169
+ t2_workflow.outputs.each do |o|
170
+ out.write "- **#{o.name}** "
171
+ if o.descriptions.size >= 1
172
+ o.descriptions.each do |desc|
173
+ out.write desc.to_s + " "
174
+ end
175
+ end
176
+ if o.examples.size >= 1
177
+ out.write "Examples include:\n\n"
178
+ o.examples.each do |ex|
179
+ out.write " - " + ex.to_s + "\n"
180
+ end
181
+ end
182
+ out.write "\n"
183
+ end
184
+ out.write "\n"
185
+ end
186
+
187
+ out.write "-----\n\n"
188
+ out.write ".. class:: warningmark\n\n"
189
+ out.write "**Please note that some workflows are not up-to-date or have dependencies** " <<
190
+ "that cannot be met by the specific Taverna server that you specified during " <<
191
+ "generation of this tool. You can make sure that the workflow is valid " <<
192
+ "by running it in the Taverna Workbench first to confirm that it works " <<
193
+ "before running it via Galaxy.\n\n"
194
+
195
+ if t2_workflow.input_type == TavernaWorkflow::MY_EXPERIMENT
196
+ out.write "-----\n\n"
197
+ out.write ".. class:: warningmark\n\n"
198
+ out.write "**Please note that there might be some repetitions in the workflow description** " <<
199
+ "in some of the generated workflows. This is due to a backwards compatibility " <<
200
+ "issue on the myExperiment repository which keeps the old descriptions to make " <<
201
+ "sure that no information is lost.\n\n"
202
+
203
+ out.write "-----\n\n"
204
+ out.write ".. class:: infomark\n\n"
205
+ out.write "**For more information on that workflow please visit** #{t2_workflow.xml_uri.gsub(/(.*workflows\/\d+)[\/.].*/, '\1')}.\n\n"
206
+ end
207
+
208
+ out.write indent(1) + "</help>\n"
209
+ end
210
+
211
+ # Galaxy's XML tool tag close
212
+ def tool_end_tag(out)
213
+ out.write("</tool>\n")
214
+ end
215
+
216
+
217
+
218
+ # Galaxy's script preample
219
+ def script_preample(out)
220
+ out.write("#!/usr/bin/env ruby\n\n")
221
+ out.write("require 'rubygems'\n")
222
+ out.write("require 't2-server'\n")
223
+ out.write("require 'open-uri'\n")
224
+ out.write("require 'zip/zipfilesystem'\n\n")
225
+ end
226
+
227
+
228
+ # Galaxy's script utility methods
229
+ # TODO: use ruby's flatten instead of our own !!!
230
+ def script_util_methods(out)
231
+
232
+ out.write <<'UTIL_METHODS'
233
+
234
+ # sends the zip file to specified output
235
+ def output_zip_file(uuid, zip_out)
236
+ File.open("/tmp/#{uuid}.zip") do |zip|
237
+ while data = zip.read(4096)
238
+ zip_out.write data
239
+ end
240
+ end
241
+ File.delete("/tmp/#{uuid}.zip")
242
+ end
243
+
244
+
245
+ #
246
+ # replicates the directory result structure as constructed by the
247
+ # taverna server and recreates it in a zip File
248
+ #
249
+ def add_to_zip_file(output_dir, data_lists, zip_out)
250
+ zip_out.dir.mkdir("#{output_dir}")
251
+ data_lists.each_with_index do |item, index|
252
+ if item.instance_of? Array
253
+ add_to_zip_file("#{output_dir}/#{index+1}", item, zip_out)
254
+ else
255
+ zip_out.file.open("#{output_dir}/#{index+1}", "w") { |f| f.puts item }
256
+ end
257
+ end
258
+ end
259
+
260
+
261
+ # method that flattens the list of list of list ... result of get_output
262
+ def print_flattened_result(out, data_lists)
263
+ data_lists.each do |l|
264
+ if l.instance_of? Array
265
+ print_flattened_result(out, l)
266
+ else
267
+ out.puts l
268
+ end
269
+ end
270
+ end
271
+
272
+
273
+ #
274
+ # Method that acquires all the results of the specified output directory.
275
+ # If valid zip File is passed it also accumulates results as a zip file.
276
+ #
277
+ def get_outputs(run, refs, outfile, dir, zip_out=nil)
278
+ data_lists = run.get_output(dir, refs)
279
+ print_flattened_result(outfile, data_lists)
280
+ if zip_out
281
+ add_to_zip_file(dir, data_lists, zip_out)
282
+ end
283
+ end
284
+
285
+
286
+ #
287
+ # Sanitize all special characters in UI inputs that Galaxy substitutes for
288
+ # security reasons. This methods turns them back to their original values before
289
+ # using them (i.e. sending them to the taverna server
290
+ # NB: note that double quote is sanitized to "'" that is because the double code
291
+ # confuses the Taverna server ruby library. Apparently, this is not trivial
292
+ # to fix.
293
+ #
294
+ def sanitize(string)
295
+ string.gsub(/(__sq__|__dq__|__at__|__cr__|__cn__|__tc__|__gt__|__lt__|__ob__|__cb__|__oc__|__cc__)/) do
296
+ if $1 == '__sq__'
297
+ "'"
298
+ elsif $1 == '__dq__'
299
+ "'"
300
+ elsif $1 == '__cr__'
301
+ "\r"
302
+ elsif $1 == '__cn__'
303
+ "\n"
304
+ elsif $1 == '__tc__'
305
+ "\t"
306
+ elsif $1 == '__gt__'
307
+ '>'
308
+ elsif $1 == '__lt__'
309
+ '<'
310
+ elsif $1 == '__ob__'
311
+ '['
312
+ elsif $1 == '__cb__'
313
+ ']'
314
+ elsif $1 == '__oc__'
315
+ '{'
316
+ elsif $1 == '__cc__'
317
+ '}'
318
+ else
319
+ '@'
320
+ end
321
+ end
322
+ end
323
+
324
+ #
325
+ # Deletes last new line of file if it exists! It is needed for t2 workflows that
326
+ # do not sanitize properly, i.e. via a user-provided beanshell script
327
+ #
328
+ def chomp_last_newline(file)
329
+
330
+ if File.file?(file) and File.size(file) > 1
331
+ f = open(file, "rb+")
332
+ f.seek(-1, File::SEEK_END)
333
+ f.truncate(File.size(file) - 1) if f.read(1) == "\n"
334
+ f.close
335
+ end
336
+
337
+ end
338
+
339
+
340
+ UTIL_METHODS
341
+
342
+ end
343
+
344
+ # Galaxy's script taverna 2 run
345
+ def script_create_t2_run(out, wkf, t2_uri)
346
+ if wkf.input_type == TavernaWorkflow::MY_EXPERIMENT
347
+ out.write "# use the uri reference to download the workflow locally\n"
348
+ out.write "wkf_file = URI.parse('#{wkf.xml_uri}')\n"
349
+ out.write "in_wkf = open(wkf_file)\n"
350
+ else # TavernaWorkflow::T2_FLOW
351
+ out.write "# uri contains local t2flow file\n"
352
+ out.write "in_wkf = open('#{wkf.xml_uri}')\n"
353
+ end
354
+
355
+ out.write <<CREATE_T2_RUN
356
+
357
+ wkf = in_wkf.read()
358
+
359
+ # create run
360
+ begin
361
+ run = T2Server::Run.create('#{t2_uri}', wkf)
362
+ rescue T2Server::T2ServerError => e
363
+ exit 1
364
+ end
365
+
366
+ CREATE_T2_RUN
367
+
368
+ end
369
+
370
+
371
+ # Galaxy's script input handling
372
+ def script_init_inputs(out, t2_workflow)
373
+ out.write "#\n"
374
+ out.write "# Get input arguments -- for each input a boolean specifies if it's from history\n"
375
+ out.write "# thus, for each t2_workflow input we have two arguments in the script!\n"
376
+ out.write "#\n"
377
+ t2_workflow.inputs.each_with_index do |input, i|
378
+ i_name = input.name.to_s
379
+ out.write "#{i_name}_from_history = ARGV[#{i*2}].chomp\n"
380
+ out.write "#{i_name}_tmp = ARGV[#{i*2+1}].chomp\n"
381
+ out.write "if #{i_name}_from_history == \"true\"\n"
382
+ out.write " chomp_last_newline(#{i_name}_tmp)\n"
383
+ out.write " run.upload_input_file('#{i_name}', #{i_name}_tmp)\n"
384
+ out.write "else\n"
385
+ out.write " run.set_input('#{i_name}', sanitize(#{i_name}_tmp))\n"
386
+ out.write "end\n"
387
+ end
388
+
389
+ # add code to handle results_as_zip input, i.e. create zip file
390
+ out.write "\n# get results_as_zip input and open zip file if appropriate\n"
391
+ # get argument index after workflow inputs
392
+ zip_index = t2_workflow.inputs.size * 2
393
+ out.write "zipped = ARGV[#{zip_index}].chomp == \"yes\"\n"
394
+ out.write 'zip_out = Zip::ZipFile.open("/tmp/#{run.uuid}.zip", Zip::ZipFile::CREATE) if zipped' + "\n"
395
+
396
+ end
397
+
398
+
399
+ # Galaxy's script starting taverna run
400
+ def script_start_run(out)
401
+ out.write <<START_RUN
402
+
403
+
404
+ # start run and wait until it is finished
405
+ run.start
406
+ run.wait(:progress => true)
407
+
408
+ START_RUN
409
+ end
410
+
411
+
412
+ # Galaxy's script output handling
413
+ def script_get_outputs(out, t2_workflow)
414
+ # outputs start after all inputs plus the results_as_zip input
415
+ outputs_start_index = t2_workflow.inputs.size * 2 + 1
416
+ outputs_end_index = outputs_start_index + t2_workflow.outputs.size - 1
417
+ out.write "# get output arguments and associated them with a file\n"
418
+ outputs_start_index.upto(outputs_end_index) do |o|
419
+ out.write "output#{o} = File.open(ARGV[#{o}], \"w\")\n"
420
+ out.write "begin\n"
421
+ out.write " get_outputs(run, false, output#{o}, '" + t2_workflow.outputs[o - outputs_start_index].name.to_s + "', zip_out)\n"
422
+ out.write "rescue Exception => err\n"
423
+ out.write " get_outputs(run, false, output#{o}, '" + t2_workflow.outputs[o - outputs_start_index].name.to_s + ".error', zip_out)\n"
424
+ out.write "ensure\n"
425
+ out.write " output#{o}.close\n"
426
+ out.write "end\n"
427
+ end
428
+
429
+ # close zip file if created when dealing with the inputs
430
+ #--
431
+ # ideally that would semantically belong to a separate method
432
+ out.write "\n# close zip_out (the newly created zip file) if opened\n"
433
+ out.write "zip_out.close if zip_out\n"
434
+
435
+ # dealing with zip output here -- zip arg index is outputs_end_index (last
436
+ # output) plus 1
437
+ out.write "\n# open galaxy zip output and write zip file\n"
438
+ out.write "if zipped\n"
439
+ out.write " galaxy_zip_out = File.open(ARGV[#{outputs_end_index+1}], \"w\")\n"
440
+ out.write " output_zip_file(run.uuid, galaxy_zip_out)\n"
441
+ out.write " galaxy_zip_out.close\n"
442
+ out.write "end\n"
443
+
444
+ end
445
+
446
+
447
+ # Galaxy's script cleaning taverna run
448
+ def script_finish_run(out)
449
+ out.write "\n# delete run\n"
450
+ out.write "run.delete\n"
451
+ end
452
+
453
+
454
+
455
+
456
+
457
+ # public methods from here onwards
458
+ public
459
+
460
+ # Generates the Galaxy tool's xml file responsible for the UI.
461
+ #
462
+ # :call-seq:
463
+ # Generator.generate_xml(my_exp_rest, xml_file) -> nil
464
+ #
465
+ # [+t2_workflow+] a _Workflow_ object as returned from <em>MyExperimentREST::Workflows.new.read(url)</em>
466
+ # [+xml_file+] a string containing the name of the generated XML file
467
+ # [+xml_out+] the file handler to write the generated XML tags
468
+ def generate_xml(t2_workflow, xml_file, xml_out)
469
+ tool_begin_tag(xml_out, t2_workflow.title)
470
+ command_tag(xml_out, t2_workflow, xml_file.gsub('.xml', '.rb'))
471
+ inputs_tag(xml_out, t2_workflow.inputs)
472
+ outputs_tag(xml_out, t2_workflow.outputs)
473
+ help_tag(xml_out, t2_workflow)
474
+ tool_end_tag(xml_out)
475
+ end
476
+
477
+
478
+ # Generates the Galaxy tool's script file responsible for talking to the
479
+ # taverna server
480
+ #
481
+ # :call-seq:
482
+ # Generator.generate_script(my_exp_rest, t2_server, script_file) -> nil
483
+ #
484
+ # [+my_exp_rest+] a _Workflow_ object as returned from <em>MyExperimentREST.ReadWorkflow.new(url)</em>
485
+ # [<tt>t2_server</tt>] a string containing the URL of the taverna 2 server
486
+ # [+script_out+] the file handler to write the generated script code
487
+ def generate_script(t2_workflow, t2_server, script_out)
488
+ script_preample(script_out)
489
+ script_util_methods(script_out)
490
+ script_create_t2_run(script_out, t2_workflow, t2_server)
491
+ script_init_inputs(script_out, t2_workflow)
492
+ script_start_run(script_out)
493
+ script_get_outputs(script_out, t2_workflow)
494
+ script_finish_run(script_out)
495
+ end
496
+
497
+ end