root/galaxy-taverna/workflow-to-galaxy/lib/workflow-to-galaxy/generator.rb @ 76

Revision 76, 8.8 KB (checked in by kostas.karasavvas@…, 3 years ago)

connected taverna inputs with galaxy outputs v0.2

Line 
1
2# Contains code to generate the Galaxy's tool xml and script files
3module Generator
4
5
6  # private methods
7  private
8
9
10  def indent(n)
11    ind = ""
12    n.times { ind += "  "  }
13    ind
14  end
15
16
17  def tool_b(out, name)
18    out.write("<tool id=\"#{name}_id\" name=\"#{name}\">\n")
19  end
20
21  def command_be(out, me_rest, script)
22    out.write indent(1) + "<command interpreter=\"ruby\">\n"
23    out.write indent(2) + script + "\n"
24    me_rest.workflow.inputs.each do |i|
25      out.write indent(2) + "#if $#{i.name}_source.history_or_textfield == \"textfield\":\n"
26      out.write indent(3) + "false \"$#{i.name}_source.textfield_#{i.name}\"\n"
27      out.write indent(2) + "#else:\n"
28      out.write indent(3) + "true  \"$#{i.name}_source.history_#{i.name}\"\n"
29      out.write indent(2) + "#end if\n"
30    end
31    out.write indent(2)
32    me_rest.workflow.outputs.each do |o|
33      out.write "$#{o.name} "
34    end
35    out.write "\n"
36    out.write indent(1) + "</command>\n"
37  end
38
39  def inputs_be(out, inputs)
40    out.write indent(1) + "<inputs>\n"
41    if inputs.size >= 1
42      inputs.each do |i|
43        out.write indent(2) + "<conditional name=\"#{i.name}_source\">\n"
44        out.write indent(3) + "<param name=\"history_or_textfield\" type=\"select\" label=\"Select source for #{i.name}\">\n"
45        out.write indent(4) + "<option value=\"history\">From history</option>\n"
46        out.write indent(4) + "<option value=\"textfield\" selected=\"true\">Type manually</option>\n"
47        out.write indent(3) + "</param>\n"
48        out.write indent(3) + "<when value=\"history\">\n"
49        out.write indent(4) + "<param name=\"history_#{i.name}\" type=\"data\" label=\"Select #{i.name}\"/>\n"
50        out.write indent(3) + "</when>\n"
51        out.write indent(3) + "<when value=\"textfield\">\n"
52        out.write indent(4) + "<param name=\"textfield_#{i.name}\" type=\"text\" size=\"30\" "
53        if i.examples.size >= 1 
54          # escape double quotes characters for galaxy's xml file
55          ex = i.examples[0].to_s.gsub('"', '&quot;')
56          out.write "value=\"#{ex}\" "         
57        end
58        out.write "label=\"Enter #{i.name}\"/>\n"
59        out.write indent(3) + "</when>\n"
60        out.write indent(2) + "</conditional>\n"
61      end
62    else
63      out.write indent(2) + "<param name=\"input\" type=\"select\" display=\"radio\" size=\"250\" label=\"This workflow has no inputs\" />\n"
64    end 
65    out.write indent(1) + "</inputs>\n"
66  end
67
68  def outputs_be(out, outputs)
69    out.write indent(1) + "<outputs>\n"
70    outputs.each do |o|
71      out.write indent(2) + "<data format=\"tabular\" name=\"#{o.name}\" label=\"#{o.name}\"/>\n"
72    end
73    out.write indent(1) + "</outputs>\n"
74  end
75
76  def help_be(out, me_rest)
77    out.write indent(1) + "<help>\n"
78    out.write "**What it does**\n\n"
79
80    # Sometimes the workflow description contains HTML tags that are not allowed
81    # in Galaxy's xml interface specification and thus are removed! Same for
82    # HTML entities!
83    out.write me_rest.workflow.description.gsub(/<.*?>|&.*?;/, '') + "\n\n"
84
85    if me_rest.workflow.inputs.size >= 1
86      out.write "-----\n\n"
87      out.write "**Inputs**\n\n"
88      me_rest.workflow.inputs.each do |i|
89        out.write "- **#{i.name}** "
90        if i.descriptions.size >= 1
91          i.descriptions.each do |desc|
92            out.write desc.to_s + " "
93          end
94        end
95        if i.examples.size >= 1
96          out.write "Examples include:\n\n"
97          i.examples.each do |ex|
98            out.write "  - " + ex.to_s + "\n"
99          end
100        end
101        out.write "\n"
102      end
103      out.write "\n"
104    end
105
106    # TODO this code is identical to the inputs code above -- method?
107    if me_rest.workflow.outputs.size >= 1
108      out.write "-----\n\n"
109      out.write "**Outputs**\n\n"
110      me_rest.workflow.outputs.each do |o|
111        out.write "- **#{o.name}** "
112        if o.descriptions.size >= 1
113          o.descriptions.each do |desc|
114            out.write desc.to_s + " "
115          end
116        end
117        if o.examples.size >= 1
118          out.write "Examples include:\n\n"
119          o.examples.each do |ex|
120            out.write "  - " + ex.to_s + "\n"
121          end
122        end
123        out.write "\n"
124      end
125      out.write "\n"
126    end
127
128    out.write "-----\n\n"
129    out.write ".. class:: warningmark\n\n"
130    out.write "**Please note that some workflows are not up-to-date or have dependencies** " <<
131              "that cannot be met by the specific Taverna server that you specified during " <<
132              "generation of this tool. You can make sure that the workflow is valid " <<
133              "by running it in the Taverna Workbench first to confirm that it works " <<
134              "before running it via Galaxy.\n\n"
135
136
137    out.write "-----\n\n"
138    out.write ".. class:: infomark\n\n"
139    out.write "**For more information on that workflow please visit** #{me_rest.uri.gsub(/(.*workflows\/\d+)[\/.].*/, '\1')}.\n\n"
140
141    out.write indent(1) + "</help>\n"
142  end
143
144  def tool_e(out)
145    out.write("</tool>\n")
146  end
147
148
149
150
151  def script_preample(out)
152    out.write("#!/usr/bin/env ruby\n\n")
153    out.write("require 'rubygems'\n")
154    out.write("require 't2-server'\n")
155    out.write("require 'open-uri'\n\n")
156  end
157
158  def script_util_methods(out)
159
160    out.write <<UTIL_METHODS
161   
162# method that flattens the list of list of list ... result of get_output
163def print_flattened_result(out, data_lists)
164  data_lists.each do |l|
165    if l.instance_of? Array
166      print_flattened_result(out, l)
167    else
168      out.puts l
169    end
170  end
171end
172
173
174# method that acquires all the results of the specified output
175def get_outputs(run, refs, outfile, dir)
176  data_lists = run.get_output(dir, refs)
177  print_flattened_result(outfile, data_lists)
178end
179
180
181#
182# Sanitize single and double quotes in str. E.g. galaxy substitutes them to
183# __sq__ and __dq__ respectively. This methods turns them back to their
184# original values before using them
185#
186def sanitize(string)
187  string.gsub(/(__sq__|__dq__|__at__)/) do
188    if $1 == '__sq__'
189      "'"
190    elsif $1 == '__dq__'
191      '\\\"'
192    else
193      '@'
194    end
195  end
196end
197
198UTIL_METHODS
199
200  end
201
202
203  def script_create_t2_run(out, wkf_uri, t2_uri)
204    out.write <<CREATE_T2_RUN
205
206# use the uri reference to download the workflow locally
207wkf_file = URI.parse('#{wkf_uri}')
208in_wkf = open(wkf_file)
209wkf = in_wkf.read()
210
211# create run
212begin
213  run = T2Server::Run.create('#{t2_uri}', wkf)
214rescue T2Server::T2ServerError => e
215  exit 1
216end
217
218CREATE_T2_RUN
219
220  end
221
222
223  def script_init_inputs(out, me_rest)
224    out.write "# get input arguments -- for each input a boolean specifies if it's from history\n"
225    out.write "# thus, for each me_rest input we have two arguments in the script!\n"
226    me_rest.workflow.inputs.each_with_index do |input, i|
227      i_name = input.name.to_s
228      out.write "#{i_name}_from_history = ARGV[#{i*2}].chomp\n"
229      out.write "#{i_name}_tmp = ARGV[#{i*2+1}].chomp\n"
230      out.write "if #{i_name}_from_history == \"true\"\n"
231      out.write "  run.upload_input_file('#{i_name}', #{i_name}_tmp)\n" #{i_name}_arg = IO.read(#{i_name}_tmp)\n"
232      out.write "else\n"
233      out.write "  run.set_input('#{i_name}', sanitize(#{i_name}_tmp))\n"  #{i_name}_arg = #{i_name}_tmp\n"
234      out.write "end\n"
235      #out.write "run.set_input('#{i_name}', sanitize(#{i_name}_arg))\n"
236    end
237
238  end
239
240
241  def script_start_run(out)
242    out.write <<START_RUN
243
244# start run and wait until it is finished
245run.start
246run.wait(:progress => true)
247
248START_RUN
249  end
250
251
252  def script_get_outputs(out, me_rest)
253    outputs_start_index = me_rest.workflow.inputs.size * 2
254    outputs_end_index = outputs_start_index + me_rest.workflow.outputs.size - 1
255    out.write "# get output arguments and associated them with a file\n"
256    outputs_start_index.upto(outputs_end_index) do |o|
257      out.write "output#{o} = File.open(ARGV[#{o}], \"w\")\n"
258      out.write "get_outputs(run, false, output#{o}, '" + me_rest.workflow.outputs[o - outputs_start_index].name.to_s + "')\n"
259    end
260
261  end
262
263
264  def script_finish_run(out)
265    out.write "\n# delete run\n"
266    out.write "run.delete\n"
267  end
268
269
270
271  # public methods from here onwards
272  public
273
274  # Generates the Galaxy tool's xml file responsible for the UI.
275  def generate_xml(me_rest, xml_file)
276    out = File.open(xml_file, "w")
277    tool_b(out, me_rest.workflow.title)
278    command_be(out, me_rest, xml_file.gsub('.xml', '.rb'))
279    inputs_be(out, me_rest.workflow.inputs)
280    outputs_be(out, me_rest.workflow.outputs)
281    help_be(out, me_rest)
282    tool_e(out)
283    out.close
284  end
285
286  #
287  # Generates the Galaxy tool's script file responsible for talking to the
288  # taverna server
289  #
290  def generate_script(me_rest, t2_server, script_file)
291    out = File.open(script_file, "w")
292    script_preample(out)
293    script_util_methods(out)
294    script_create_t2_run(out, me_rest.uri, t2_server)
295    script_init_inputs(out, me_rest)
296    script_start_run(out)
297    script_get_outputs(out, me_rest)
298    script_finish_run(out)
299    out.close
300  end
301
302end
Note: See TracBrowser for help on using the browser.