coderunner 0.14.23 → 0.14.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8e1deca0aeb33a5da186b2c08c94945d7561cdf4
4
+ data.tar.gz: f97f58aba34eea4c3221d16ad88316a28b93e241
5
+ SHA512:
6
+ metadata.gz: 3db503c9c435107ade3384de8f9364e645ae84e4363ff28f33b3df831014991ad1511fadd082d67eb108ec5aba4158ac65ae50826d0a6c20f3dc86d9efac4066
7
+ data.tar.gz: 71f72f4d1324706d49e10e7a2dbda39b90efd5b6c79518127aef12dd6d86437fc9d721a51366d13763dec467e44f15ed04a913ebc48ece427045aea65163d753
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.14.23
1
+ 0.14.24
@@ -2,14 +2,17 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: coderunner 0.14.24 ruby lib
6
+ # stub: ext/extconf.rb
5
7
 
6
8
  Gem::Specification.new do |s|
7
9
  s.name = "coderunner"
8
- s.version = "0.14.23"
10
+ s.version = "0.14.24"
9
11
 
10
12
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
13
+ s.require_paths = ["lib"]
11
14
  s.authors = ["Edmund Highcock"]
12
- s.date = "2014-08-29"
15
+ s.date = "2014-10-10"
13
16
  s.description = "CodeRunner is a framework for the automated running and analysis of simulations. It automatically generates any necessary input files, organises the output data and analyses it. Because it is a modular system, it can easily be customised to work with any system and any simulation code. One of its greatest strengths is that it is independent of any one simulation code; thus it can easily plot and compare the data from different codes."
14
17
  s.email = "edmundhighcock@sourceforge.net"
15
18
  s.executables = ["coderunner"]
@@ -89,14 +92,13 @@ Gem::Specification.new do |s|
89
92
  ]
90
93
  s.homepage = "http://coderunner.sourceforge.net"
91
94
  s.licenses = ["GPLv3"]
92
- s.require_paths = ["lib"]
93
95
  s.required_ruby_version = Gem::Requirement.new(">= 1.9.1")
94
96
  s.rubyforge_project = "coderunner"
95
- s.rubygems_version = "1.8.11"
97
+ s.rubygems_version = "2.2.2"
96
98
  s.summary = "A framework for the automated running and analysis of simulations."
97
99
 
98
100
  if s.respond_to? :specification_version then
99
- s.specification_version = 3
101
+ s.specification_version = 4
100
102
 
101
103
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
102
104
  s.add_runtime_dependency(%q<graphkit>, [">= 0.3.2"])
@@ -131,7 +131,7 @@ class CodeRunner
131
131
 
132
132
 
133
133
  # Here are all the methods that map the command line invocation into the correct class method call
134
- COMMAND_LINE_FLAGS_WITH_HELP = [
134
+ COMMAND_LINE_FLAGS_WITH_HELP = [
135
135
  ["--recalc-all", "-A", GetoptLong::NO_ARGUMENT, %[Causes each directory to be reprocessed, rather than reading the cache of data. Its exact effect depends on the code module being used. By convention it implies that ALL data analysis will be redone.]],
136
136
  ["--reprocess-all", "-a", GetoptLong::NO_ARGUMENT, %[Causes each directory to be reprocessed, rather than reading the cache of data. Its exact effect depends on the code module being used. By convention it implies that VERY LITTLE data analysis will be redone.]],
137
137
  ["--code", "-C", GetoptLong::REQUIRED_ARGUMENT, %[The code that is being used for simulations in this folder. This string must correspond to a code module supplied to CodeRunner. It usually only needs to be specified once as it will be stored as a default in the folder.]],
@@ -1,86 +1,86 @@
1
1
  class CodeRunner
2
-
3
- # In the next section are the implementations of all the standard Code Runner commands and some helper functions.
4
-
5
- def self.set_runner_defaults(copts = {})
6
- (DEFAULT_RUNNER_OPTIONS.keys - [:sys, :script_folder]).each do |var|
7
- DEFAULT_RUNNER_OPTIONS[var] = copts[LONG_TO_SHORT[var]]
8
- end
9
- set_class_defaults(copts)
10
- # ep DEFAULT_RUNNER_OPTIONS
11
- end
12
-
13
- def self.set_class_defaults(copts={})
14
- (CLASS_OPTIONS.keys - []).each do |var|
15
- CLASS_OPTIONS[var] = copts[LONG_TO_SHORT[var]]
16
- set(var, CLASS_OPTIONS[var])
17
- end
18
- end
19
-
20
- # List the available modlets for the given code (copts[:C] or -C on the command line).
21
-
22
- def self.available_modlets(copts={})
23
- process_command_options(copts)
24
- puts "\nAvailable modlets for #{copts[:C]}:"
25
- entries = []
26
- begin
27
- entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_modlets")
28
- rescue
29
- end
30
- begin
31
- entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/default_modlets")
32
- rescue
33
- end
34
- entries.each do |modlet|
35
- puts "\t" + File.basename(modlet, '.rb') unless ['.', '..', '.svn', '.directory'].include? modlet or modlet=~ /defaults/
36
- end
37
- end
38
-
39
- # List the available defaults files for the given code (copts[:C] or -C on the command line).
40
-
41
- def self.available_defaults_files(copts={})
42
- process_command_options(copts)
43
- entries = []
44
- #begin
45
- ##entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_defaults_files")
46
- #entries +=
47
- #rescue
48
- #end
49
- #begin
50
- #run_class = setup_run_class(copts[:C], modlet: copts[:m])
51
- rc = run_class(copts)
52
- entries = [rc.rcp.user_defaults_location, rc.rcp.code_module_folder + "/defaults_files"].map{|folder| Dir.entries(folder).grep(/_defaults\.rb$/) rescue []}.sum
53
- #entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
54
- #entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
55
- #rescue
56
- #end
57
- puts "\nAvailable defaults files for #{copts[:C]}:"
58
- entries.each do |defaults_file|
59
- #puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '') unless ['.', '..', '.svn', '.directory'].include? defaults_file
60
- puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '')
61
- end
62
- end
63
-
64
- # Cancel the job with the given id. The user is asked interactively for confirmation and whether they would like to delete the folder for that job as well.
65
-
66
- def self.cancel(id, copts={})
67
- runner = fetch_runner(copts)
68
- runner.cancel_job(id.to_i)
69
- end
70
-
71
- def self.continue_in_new_folder(folder, copts={})
72
- runner=fetch_runner(copts)
73
- options = {}
74
- if copts[:f] or copts[:j]
75
- options[:copy_ids] = runner.filtered_ids
76
- end
77
-
78
- runner.continue_in_new_folder(folder, options)
79
- end
80
-
2
+
3
+ # In the next section are the implementations of all the standard Code Runner commands and some helper functions.
4
+
5
+ def self.set_runner_defaults(copts = {})
6
+ (DEFAULT_RUNNER_OPTIONS.keys - [:sys, :script_folder]).each do |var|
7
+ DEFAULT_RUNNER_OPTIONS[var] = copts[LONG_TO_SHORT[var]]
8
+ end
9
+ set_class_defaults(copts)
10
+ # ep DEFAULT_RUNNER_OPTIONS
11
+ end
12
+
13
+ def self.set_class_defaults(copts={})
14
+ (CLASS_OPTIONS.keys - []).each do |var|
15
+ CLASS_OPTIONS[var] = copts[LONG_TO_SHORT[var]]
16
+ set(var, CLASS_OPTIONS[var])
17
+ end
18
+ end
19
+
20
+ # List the available modlets for the given code (copts[:C] or -C on the command line).
21
+
22
+ def self.available_modlets(copts={})
23
+ process_command_options(copts)
24
+ puts "\nAvailable modlets for #{copts[:C]}:"
25
+ entries = []
26
+ begin
27
+ entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_modlets")
28
+ rescue
29
+ end
30
+ begin
31
+ entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/default_modlets")
32
+ rescue
33
+ end
34
+ entries.each do |modlet|
35
+ puts "\t" + File.basename(modlet, '.rb') unless ['.', '..', '.svn', '.directory'].include? modlet or modlet=~ /defaults/
36
+ end
37
+ end
38
+
39
+ # List the available defaults files for the given code (copts[:C] or -C on the command line).
40
+
41
+ def self.available_defaults_files(copts={})
42
+ process_command_options(copts)
43
+ entries = []
44
+ #begin
45
+ ##entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/my_defaults_files")
46
+ #entries +=
47
+ #rescue
48
+ #end
49
+ #begin
50
+ #run_class = setup_run_class(copts[:C], modlet: copts[:m])
51
+ rc = run_class(copts)
52
+ entries = [rc.rcp.user_defaults_location, rc.rcp.code_module_folder + "/defaults_files"].map{|folder| Dir.entries(folder).grep(/_defaults\.rb$/) rescue []}.sum
53
+ #entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
54
+ #entries += Dir.entries(SCRIPT_FOLDER + "/code_modules/#{copts[:C]}/defaults_files")
55
+ #rescue
56
+ #end
57
+ puts "\nAvailable defaults files for #{copts[:C]}:"
58
+ entries.each do |defaults_file|
59
+ #puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '') unless ['.', '..', '.svn', '.directory'].include? defaults_file
60
+ puts "\t" + File.basename(defaults_file, '.rb').sub(/_defaults/, '')
61
+ end
62
+ end
63
+
64
+ # Cancel the job with the given id. The user is asked interactively for confirmation and whether they would like to delete the folder for that job as well.
65
+
66
+ def self.cancel(id, copts={})
67
+ runner = fetch_runner(copts)
68
+ runner.cancel_job(id.to_i)
69
+ end
70
+
71
+ def self.continue_in_new_folder(folder, copts={})
72
+ runner=fetch_runner(copts)
73
+ options = {}
74
+ if copts[:f] or copts[:j]
75
+ options[:copy_ids] = runner.filtered_ids
76
+ end
77
+
78
+ runner.continue_in_new_folder(folder, options)
79
+ end
80
+
81
81
  # This section defines the report report writing function in. The latex header is defined in run.rb. It is a run method and can be redefined in a particular CRMOD.
82
82
  # The function is simply called as follows:
83
- #
83
+ #
84
84
  # interactively: wr j:<run no.>
85
85
  # command line: coderunner write_report -j <run no>
86
86
  #
@@ -90,12 +90,12 @@ class CodeRunner
90
90
  # 2. gnuplot
91
91
  # 3. ability to write eps graphs
92
92
  #
93
- # The graphs which are written out to the PDF are read in from a given CRMOD. It should be defined in the main .rb file for the CRMOD, e.g. gs2.rb.
93
+ # The graphs which are written out to the PDF are read in from a given CRMOD. It should be defined in the main .rb file for the CRMOD, e.g. gs2.rb.
94
94
  # As seen below, this function should be called 'latex_graphs'. To see an example of what this function should look like see GS2CRMOD, but it is simply an array of graphkits
95
95
  # and latex code blocks which describe plots.
96
96
  def self.write_report(copts={})
97
97
  runner = fetch_runner(copts)
98
- runs = runner.filtered_ids.map{|id| runner.combined_run_list[id]}
98
+ runs = runner.filtered_ids.map{|id| runner.combined_run_list[id]}
99
99
 
100
100
  #Loop through the runs and write a latex file for each
101
101
  runs.each do |r|
@@ -105,7 +105,7 @@ class CodeRunner
105
105
  Dir.chdir("run_docs/id_#{r.id}") do
106
106
 
107
107
  File.open("summary.tex", 'w') do |file|
108
- file.puts r.latex_report_header
108
+ file.puts r.latex_report_header
109
109
  file.puts <<-EOF.gsub(/^ {14}/, "")
110
110
  \\begin{itemize}
111
111
  EOF
@@ -114,7 +114,7 @@ class CodeRunner
114
114
  #then generates the latex code to display graphs.
115
115
  latex_code = r.latex_graphs.inject("") do |tmp_latex_code, (kit, latexstring)|
116
116
  kit.gnuplot_write(kit.file_name) #write the graph
117
- tmp_latex_code += "\\item " + latexstring + " \n\n\\newfig{#{kit.file_name}}"
117
+ tmp_latex_code += "\\item " + latexstring + " \n\n\\newfig{#{kit.file_name}}"
118
118
  tmp_latex_code += "\n\n"
119
119
  tmp_latex_code
120
120
  end
@@ -125,195 +125,195 @@ class CodeRunner
125
125
  \\end{document}
126
126
  EOF
127
127
  end #file write
128
- system "pdflatex summary.tex"
128
+ system "pdflatex summary.tex"
129
129
  end
130
130
  end #chdir
131
- end # run loop
132
- end
133
-
134
- def self.delete(copts={})
135
- runner = fetch_runner(copts)
136
- runner.destroy
137
- end
138
- def self.differences_between(copts = {})
139
- runner = fetch_runner(copts)
140
- runs = runner.filtered_ids.map{|id| runner.combined_run_list[id]}
141
- rcp_fetcher = (runs[0] || runner.run_class).rcp
142
- vars = rcp_fetcher.variables.dup + rcp_fetcher.run_info.dup
143
- vars.delete_if{|var| runs.map{|r| r.send(var)}.uniq.size == 1}
144
- vars.delete :id
145
- vars.delete :run_name
146
- vars.delete :output_file
147
- vars.delete :error_file
148
- vars.delete :executable
149
- vars.delete :comment
150
- vars.delete :naming_pars
151
- vars.delete :parameter_hash
152
- vars.unshift :id
153
- #vars.push 'File.basename(executable)'
154
- table = vars.map{|var| [var] + runs.map{|r| str = r.instance_eval(var.to_s).to_s; str.size>10?str[0..9]:str} }
155
- #vars[-1] = 'exec'
156
- col_widths = table.map{|row| row.map{|v| v.to_s.size}}.inject{|o,n| o.zip(n).map{|a| a.max}}
157
- eputs
158
- table.each{|row| i=0; eputs row.map{|v| str = sprintf(" %#{col_widths[i]}s ", v.to_s); i+=1; str}.join('|'); eputs '-' * (col_widths.sum + col_widths.size*3 - 1) }
159
- #p table, col_widths
160
- end
161
-
162
- def self.dumb_film(copts = {})
163
- # process_copts(copts)
164
- #old_term = GraphKit::GNUPLOT_DEFAULT_TERM
165
- size = Terminal.terminal_size
166
- size[0] -= 2
167
- term = "dumb #{size.reverse.join(' ')}"
168
- string = "\n" * size[0]
169
-
170
- runner = fetch_runner(copts)
171
- string_to_eval = copts[:w]
172
- frame_array = copts[:F][:frame_array] || copts[:F][:fa]
173
- index_name = copts[:F][:index_name] || copts[:F][:in]
174
- #options = (options and options =~ /\S/) ? eval(options): {}
175
- puts string
176
- for index in frame_array[0]..frame_array[1]
177
- string.true_lines.times{print "\033[A"}
178
- kit = runner.graphkit_from_lists(copts[:G], copts[:g], index_name => index)
131
+ end # run loop
132
+ end
133
+
134
+ def self.delete(copts={})
135
+ runner = fetch_runner(copts)
136
+ runner.destroy
137
+ end
138
+ def self.differences_between(copts = {})
139
+ runner = fetch_runner(copts)
140
+ runs = runner.filtered_ids.map{|id| runner.combined_run_list[id]}
141
+ rcp_fetcher = (runs[0] || runner.run_class).rcp
142
+ vars = rcp_fetcher.variables.dup + rcp_fetcher.run_info.dup
143
+ vars.delete_if{|var| runs.map{|r| r.send(var)}.uniq.size == 1}
144
+ vars.delete :id
145
+ vars.delete :run_name
146
+ vars.delete :output_file
147
+ vars.delete :error_file
148
+ vars.delete :executable
149
+ vars.delete :comment
150
+ vars.delete :naming_pars
151
+ vars.delete :parameter_hash
152
+ vars.unshift :id
153
+ #vars.push 'File.basename(executable)'
154
+ table = vars.map{|var| [var] + runs.map{|r| str = r.instance_eval(var.to_s).to_s; str.size>10?str[0..9]:str} }
155
+ #vars[-1] = 'exec'
156
+ col_widths = table.map{|row| row.map{|v| v.to_s.size}}.inject{|o,n| o.zip(n).map{|a| a.max}}
157
+ eputs
158
+ table.each{|row| i=0; eputs row.map{|v| str = sprintf(" %#{col_widths[i]}s ", v.to_s); i+=1; str}.join('|'); eputs '-' * (col_widths.sum + col_widths.size*3 - 1) }
159
+ #p table, col_widths
160
+ end
161
+
162
+ def self.dumb_film(copts = {})
163
+ # process_copts(copts)
164
+ #old_term = GraphKit::GNUPLOT_DEFAULT_TERM
165
+ size = Terminal.terminal_size
166
+ size[0] -= 2
167
+ term = "dumb #{size.reverse.join(' ')}"
168
+ string = "\n" * size[0]
169
+
170
+ runner = fetch_runner(copts)
171
+ string_to_eval = copts[:w]
172
+ frame_array = copts[:F][:frame_array] || copts[:F][:fa]
173
+ index_name = copts[:F][:index_name] || copts[:F][:in]
174
+ #options = (options and options =~ /\S/) ? eval(options): {}
175
+ puts string
176
+ for index in frame_array[0]..frame_array[1]
177
+ string.true_lines.times{print "\033[A"}
178
+ kit = runner.graphkit_from_lists(copts[:G], copts[:g], index_name => index)
179
179
  kit.gp.term = term
180
- kit.gnuplot(eval: string_to_eval)
181
- sleep(copts[:F][:fr] ? 1.0/copts[:F][:fr] : 0.1)
182
- end
183
- end
184
- # def self.executable_name # :nodoc:
185
- # ""
186
- # end
187
- #
188
- # def self.rcp # :nodoc:
189
- # @rcp ||= KitHash.new
190
- # end
191
- def self.netcdf_plot(netcdf_file, vars, indices, copts={})
192
- process_command_options(copts)
193
- begin
194
- require "numru/netcdf"
195
- rescue LoadError
196
- eputs "Error: No Ruby NetCDF library (was it installed correctly?): data analysis for netcdf files not possible."
197
- return
198
- end
199
- start_indices = indices.split(',').map{|idx| idx = idx.split(':')[0] if idx =~ /:/ ; eval(idx) || 0}
200
- end_indices = indices.split(',').map{|idx| idx = idx.split(':')[1] if idx =~ /:/ ; eval(idx) || -1}
201
-
202
- ep 'start_indices', start_indices, 'end_indices', end_indices
203
- file = NumRu::NetCDF.open(netcdf_file)
204
- to_plot = vars.split(',').map do |var|
205
- ep 'var', var
206
- [file.var(var).get('start'=> start_indices, 'end'=> end_indices).to_a.flatten]
207
- end
208
- ep 'to_plot', to_plot
209
- kit = GraphKit.quick_create(*to_plot)
210
- ep 'copts', copts
211
- kit.instance_eval(copts[:w]) if copts[:w]
212
- kit.gnuplot
213
- STDIN.gets
214
- kit.close
215
- end
216
-
217
-
218
-
219
- def self.print_queue_status(copts={})
220
- begin
221
- eputs queue_status
222
- rescue => err
223
- eputs "General queue status doesn't work on this system; showing queue status for this folder"
224
- # p err
225
- runner = fetch_runner(copts)
226
- eputs runner.queue_status
227
- end
228
- end
229
-
230
-
231
-
232
-
233
-
234
- def self.reference(class_or_method, copts={})
235
- code_folders = Dir.recursive_entries(SCRIPT_FOLDER + '/code_modules').grep(/\/ri$/).map{|fold| ['-d', fold]}.flatten
236
- # ep code_folders
237
-
238
- # require 'rdoc/ri/driver'
239
-
180
+ kit.gnuplot(eval: string_to_eval)
181
+ sleep(copts[:F][:fr] ? 1.0/copts[:F][:fr] : 0.1)
182
+ end
183
+ end
184
+ # def self.executable_name # :nodoc:
185
+ # ""
186
+ # end
187
+ #
188
+ # def self.rcp # :nodoc:
189
+ # @rcp ||= KitHash.new
190
+ # end
191
+ def self.netcdf_plot(netcdf_file, vars, indices, copts={})
192
+ process_command_options(copts)
193
+ begin
194
+ require "numru/netcdf"
195
+ rescue LoadError
196
+ eputs "Error: No Ruby NetCDF library (was it installed correctly?): data analysis for netcdf files not possible."
197
+ return
198
+ end
199
+ start_indices = indices.split(',').map{|idx| idx = idx.split(':')[0] if idx =~ /:/ ; eval(idx) || 0}
200
+ end_indices = indices.split(',').map{|idx| idx = idx.split(':')[1] if idx =~ /:/ ; eval(idx) || -1}
201
+
202
+ ep 'start_indices', start_indices, 'end_indices', end_indices
203
+ file = NumRu::NetCDF.open(netcdf_file)
204
+ to_plot = vars.split(',').map do |var|
205
+ ep 'var', var
206
+ [file.var(var).get('start'=> start_indices, 'end'=> end_indices).to_a.flatten]
207
+ end
208
+ ep 'to_plot', to_plot
209
+ kit = GraphKit.quick_create(*to_plot)
210
+ ep 'copts', copts
211
+ kit.instance_eval(copts[:w]) if copts[:w]
212
+ kit.gnuplot
213
+ STDIN.gets
214
+ kit.close
215
+ end
216
+
217
+
218
+
219
+ def self.print_queue_status(copts={})
220
+ begin
221
+ eputs queue_status
222
+ rescue => _err
223
+ eputs "General queue status doesn't work on this system; showing queue status for this folder"
224
+ # p err
225
+ runner = fetch_runner(copts)
226
+ eputs runner.queue_status
227
+ end
228
+ end
229
+
230
+
231
+
232
+
233
+
234
+ def self.reference(class_or_method, copts={})
235
+ code_folders = Dir.recursive_entries(SCRIPT_FOLDER + '/code_modules').grep(/\/ri$/).map{|fold| ['-d', fold]}.flatten
236
+ # ep code_folders
237
+
238
+ # require 'rdoc/ri/driver'
239
+
240
240
  # "
241
- # op = @ri_count ? [] : (@ri_count = true; ['--no-use-cache'])
242
- # trap(1){puts 'No help available'}
243
- # at_exit{raise ""}
244
- # p op
245
- begin
246
- eputs "Looking up #{class_or_method}"
247
- RDoc::RI::Driver.run ['-d', SCRIPT_FOLDER + '/ri', class_or_method.to_s] + code_folders
248
- rescue => err
249
- eputs "Unknown class or method or no help available: #{err}"
250
- end
251
- # trap(1){}
252
- end
253
-
254
-
255
- def self.directory(id, copts={})
256
- runner = fetch_runner(copts)
257
- puts runner.run_list[id.to_i].directory
258
- end
259
- def self.film(copts={})
260
- runner = fetch_runner(copts)
261
- copts[:F][:graphkit_modify] = copts[:w]
262
- runner.make_film_from_lists(copts[:G], copts[:g], copts[:F])
263
- end
264
-
265
- def self.generate_documentation(username = nil, copts = {})
266
- ep 'username', username||=ENV['USER']
267
-
268
- ####### Here we use the command line documentation to generate a fake ruby file that rdoc will understand.
269
- File.open("class_methods_rdoc.rb", 'w') do |file|
270
- file.puts <<EOF
241
+ # op = @ri_count ? [] : (@ri_count = true; ['--no-use-cache'])
242
+ # trap(1){puts 'No help available'}
243
+ # at_exit{raise ""}
244
+ # p op
245
+ begin
246
+ eputs "Looking up #{class_or_method}"
247
+ RDoc::RI::Driver.run ['-d', SCRIPT_FOLDER + '/ri', class_or_method.to_s] + code_folders
248
+ rescue => err
249
+ eputs "Unknown class or method or no help available: #{err}"
250
+ end
251
+ # trap(1){}
252
+ end
253
+
254
+
255
+ def self.directory(id, copts={})
256
+ runner = fetch_runner(copts)
257
+ puts runner.run_list[id.to_i].directory
258
+ end
259
+ def self.film(copts={})
260
+ runner = fetch_runner(copts)
261
+ copts[:F][:graphkit_modify] = copts[:w]
262
+ runner.make_film_from_lists(copts[:G], copts[:g], copts[:F])
263
+ end
264
+
265
+ def self.generate_documentation(username = nil, copts = {})
266
+ ep 'username', username||=ENV['USER']
267
+
268
+ ####### Here we use the command line documentation to generate a fake ruby file that rdoc will understand.
269
+ File.open("class_methods_rdoc.rb", 'w') do |file|
270
+ file.puts <<EOF
271
271
  class CodeRunner
272
-
273
-
274
- #{COMMANDS_WITH_HELP.inject("") do |str, (long, short, nargs, comhelp, argnames, options)|
275
- (puts "Please run this command in the coderunner trunk directory"; exit) unless Dir.pwd =~ /coderunner\/trunk$/
276
- str << <<EOF2
272
+
273
+
274
+ #{COMMANDS_WITH_HELP.inject("") do |str, (long, _short, _nargs, comhelp, argnames, options)|
275
+ (puts "Please run this command in the coderunner trunk directory"; exit) unless Dir.pwd =~ /coderunner\/trunk$/
276
+ str << <<EOF2
277
277
  # #{comhelp.gsub(/\n/, "\n # ")}
278
278
  #
279
279
  # Possible options:
280
280
  #
281
- #{options.inject("") do |str, opt|
282
- longop, shortop, req, ophelp = COMMAND_LINE_FLAGS_WITH_HELP.find{|arr| arr[1] == "-" + opt.to_s}
283
- str << " # :#{opt} --- #{ophelp.gsub(/\n/, "\n # ")}\n #\n"
284
- end}
285
-
286
- def self.#{long}(#{(argnames+[""]).join(",")}command_options={})
287
- end
288
-
281
+ #{options.inject("") do |strr, opt|
282
+ _longop, _shortop, _req, ophelp = COMMAND_LINE_FLAGS_WITH_HELP.find{|arr| arr[1] == "-" + opt.to_s}
283
+ strr << " # :#{opt} --- #{ophelp.gsub(/\n/, "\n # ")}\n #\n"
284
+ end}
285
+
286
+ def self.#{long}(#{(argnames+[""]).join(",")}command_options={})
287
+ end
288
+
289
289
  EOF2
290
- end
291
- }
290
+ end
291
+ }
292
292
  end
293
293
  EOF
294
- end
295
- # exit
296
-
297
- system "rm -rf doc/"
298
- system "rm -rf ri/"
299
- raise 'Please set RDOC_COMMAND' unless ENV['RDOC_COMMAND']
300
- system "#{ENV['RDOC_COMMAND']} --format=html -t 'CodeRunner Documentation' -m INDEX.rb INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb class_methods_rdoc.rb instance_methods.rb"
301
- system "#{ENV['RDOC_COMMAND']} -r --op ri INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb class_methods_rdoc.rb instance_methods.rb"
302
-
303
- exit if username == ""
304
-
305
- string = "rsync -av --delete doc/ #{username},coderunner@web.sourceforge.net:htdocs/api_documentation/"
306
-
307
- puts string
308
- exec string
309
-
310
- end
311
-
312
-
313
- def self.generate_cubecalc(copts={})
314
- #return
315
- File.open('cubecalc.cc', 'w') do |file|
316
- file.puts <<EOF
294
+ end
295
+ # exit
296
+
297
+ system "rm -rf doc/"
298
+ system "rm -rf ri/"
299
+ raise 'Please set RDOC_COMMAND' unless ENV['RDOC_COMMAND']
300
+ system "#{ENV['RDOC_COMMAND']} --format=html -t 'CodeRunner Documentation' -m INDEX.rb INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb class_methods_rdoc.rb instance_methods.rb"
301
+ system "#{ENV['RDOC_COMMAND']} -r --op ri INDEX.rb code_runner_version.rb gnuplot.rb graphkit_gnuplot.rb graphkit.rb gsl_tools.rb run_backwards_compatibility.rb feedback.rb run.rb fortran_namelist.rb graphs_and_films.rb class_methods_rdoc.rb instance_methods.rb"
302
+
303
+ exit if username == ""
304
+
305
+ string = "rsync -av --delete doc/ #{username},coderunner@web.sourceforge.net:htdocs/api_documentation/"
306
+
307
+ puts string
308
+ exec string
309
+
310
+ end
311
+
312
+
313
+ def self.generate_cubecalc(copts={})
314
+ #return
315
+ File.open('cubecalc.cc', 'w') do |file|
316
+ file.puts <<EOF
317
317
  #include <stdio.h>
318
318
  #include <iostream>
319
319
  #include <cstdlib>
@@ -323,563 +323,565 @@ EOF
323
323
  using namespace std;
324
324
 
325
325
  int main(int argc, char* argv[]){
326
- string line;
327
- cout << "Starting..." << endl;
328
-
329
- int calculate_sides = atoi(argv[1]); //Should the program calculate the area of the sides of the cube?
330
- cout << calculate_sides << endl;
331
-
332
- char* input_file_name = argv[2]; //Get the input file name from the command line
333
- cout << input_file_name << endl;
334
-
335
- if (argc > 3){ //It has been told to sleep for a time
336
- bool cont = true;
337
- time_t start_t;
338
- time(&start_t);
339
- while (cont){
340
- time_t new_t;
341
- time(&new_t);
342
- cont = (new_t < (start_t + atoi(argv[3]) * 1.0));
343
- }
344
- }
345
-
346
- ifstream edges_file(input_file_name); //Read the edges from the input file
347
- float* edges = new float[3];
348
- int j = 0;
349
- while (edges_file >> edges[j++]){
350
- cout << edges[j-1] << endl;
351
- }
352
-
353
-
354
- FILE* output = fopen("results.txt", "w"); //Write the volume to the output file
355
- fprintf(output, "Volume was %f", edges[0] * edges[1] * edges[2]);
356
- fclose(output);
357
-
358
- if (calculate_sides == 1){ //If it has been told to calculate the sides
359
- cout << "calculating sides" << endl;
360
- FILE* sides = fopen("sides.txt", "w");
361
- for(int i=0; i<3; i++){
362
- cout << "Side " << i << ": " << edges[(i%3)] * edges[((i+1)%3)] << endl;
363
- fprintf(sides, "The area of side %d is %f\\n", i, edges[i%3] * edges[(i+1)%3]);
364
- }
365
- fclose(sides);
366
- }
326
+ string line;
327
+ cout << "Starting..." << endl;
328
+
329
+ int calculate_sides = atoi(argv[1]); //Should the program calculate the area of the sides of the cube?
330
+ cout << calculate_sides << endl;
331
+
332
+ char* input_file_name = argv[2]; //Get the input file name from the command line
333
+ cout << input_file_name << endl;
334
+
335
+ if (argc > 3){ //It has been told to sleep for a time
336
+ bool cont = true;
337
+ time_t start_t;
338
+ time(&start_t);
339
+ while (cont){
340
+ time_t new_t;
341
+ time(&new_t);
342
+ cont = (new_t < (start_t + atoi(argv[3]) * 1.0));
343
+ }
344
+ }
345
+
346
+ ifstream edges_file(input_file_name); //Read the edges from the input file
347
+ float* edges = new float[3];
348
+ int j = 0;
349
+ while (edges_file >> edges[j++]){
350
+ cout << edges[j-1] << endl;
351
+ }
352
+
353
+
354
+ FILE* output = fopen("results.txt", "w"); //Write the volume to the output file
355
+ fprintf(output, "Volume was %f", edges[0] * edges[1] * edges[2]);
356
+ fclose(output);
357
+
358
+ if (calculate_sides == 1){ //If it has been told to calculate the sides
359
+ cout << "calculating sides" << endl;
360
+ FILE* sides = fopen("sides.txt", "w");
361
+ for(int i=0; i<3; i++){
362
+ cout << "Side " << i << ": " << edges[(i%3)] * edges[((i+1)%3)] << endl;
363
+ fprintf(sides, "The area of side %d is %f\\n", i, edges[i%3] * edges[(i+1)%3]);
364
+ }
365
+ fclose(sides);
366
+ }
367
367
  }
368
-
368
+
369
369
 
370
370
 
371
371
  EOF
372
372
 
373
- end
374
- end
375
- def self.launcher_directory
376
- ENV['HOME'] + "/.coderunner/to_launch/#{ENV['CODE_RUNNER_LAUNCHER']}"
377
- end
373
+ end
374
+ end
375
+ def self.launcher_directory
376
+ ENV['HOME'] + "/.coderunner/to_launch/#{ENV['CODE_RUNNER_LAUNCHER']}"
377
+ end
378
378
  def self.start_launcher(refresh, max_queue, copts={})
379
- #eputs "Starting launcher!"
380
- raise "Raise refresh is #{refresh}: it must be >= 0.1" if refresh.to_f < 0.1
381
- raise "Raise max_queue is #{max_queue}: it must be >= 5" if max_queue.to_i < 5
379
+ #eputs "Starting launcher!"
380
+ raise "Raise refresh is #{refresh}: it must be >= 0.1" if refresh.to_f < 0.1
381
+ raise "Raise max_queue is #{max_queue}: it must be >= 5" if max_queue.to_i < 5
382
382
  #raise "Launcher already running" if %x[ps -e -o cmd].split("\n").grep(/coderunner\s+launch/).size > 0
383
383
  require 'thread'
384
384
  tl = launcher_directory #SCRIPT_FOLDER + '/to_launch'
385
- #exit unless Feedback.get_boolean( "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?") if FileTest.exist? tl
386
- raise "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?" if FileTest.exist? tl
385
+ #exit unless Feedback.get_boolean( "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?") if FileTest.exist? tl
386
+ raise "Launch directory #{tl} already exists: it is suggested that you change the prefix by changing the environment variable CODE_RUNNER_LAUNCHER. Do you wish to continue (don't select yes unless you know what you are doing)?" if FileTest.exist? tl
387
387
  # FileUtils.rm_r tl if FileTest.exist? tl
388
388
  eputs "Starting launcher\n"
389
- at_exit{FileUtils.rm_r tl}
389
+ at_exit{FileUtils.rm_r tl}
390
390
  FileUtils.makedirs tl
391
391
 
392
- unless ENV['CODE_RUNNER_LAUNCHER'] =~ /serial/
393
- Thread.new{loop{`cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`; sleep 1}}
394
-
395
- mutex = Mutex.new
396
- processes= []
397
-
398
- Thread.new do
399
- loop do
400
- Dir.entries(tl).each do |file|
401
- next unless file =~ (/(^.*)\.stop/)
402
- pid = $1
403
- mutex.synchronize{Process.kill(pid); processes.delete pid}
404
- end
405
- sleep refresh.to_i
406
- end
407
- end
408
-
409
- #Dir.chdir(tl) do
410
- ppid = $$
411
- loop do
412
- sleep refresh.to_i while processes.size >= max_queue.to_i
413
- # processes = []
414
- Dir.entries(tl).grep(/(^.*)\.start/).each do |file|
415
- file =~ (/(^.*)\.start/)
416
- id = $1
417
- command = ""
418
- command = File.read tl + '/' + file while command == ""
419
- pid = fork do
420
- processes.each do |wpid|
421
- # Make sure all previously submitted jobs have finished.
422
- sleep refresh.to_i while %x[ps -e -o pid,ppid].split("\n").grep(Regexp.new("^\\s*#{wpid}\\s+#{ppid}")).size > 0
423
- end
424
- #p ["command", command]
425
- exec(command + "; wait")
426
- end
427
- `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`
428
- mutex.synchronize{processes.push pid}
429
-
430
- File.open(tl + '/' + id + '.pid', 'w'){|file| file.puts pid}
431
- FileUtils.rm(tl + '/' + file)
432
-
433
- Thread.new{Process.wait pid; mutex.synchronize{processes.delete pid}}
434
- end
435
- # processes.each{|pid| Process.wait pid}
436
- sleep refresh.to_i
437
- end
438
- #end
439
- #
440
- else
441
- loop do
442
- Dir.entries(tl).grep(/(^.*)\.start/).each do |file|
443
- file =~ (/(^.*)\.start/)
444
- id = $1
445
- command = ""
446
- command = File.read tl + '/' + file while command == ""
447
- pid = 12345
448
- File.open(tl + '/' + id + '.pid', 'w'){|file| file.puts pid}
449
- File.open("#{tl}/queue_status.txt", "w"){|file| file.puts pid}
450
- `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt`
451
- FileUtils.rm(tl + '/' + file)
452
- system "#{command} \n\n wait \n\n"
453
- File.open("#{tl}/queue_status.txt", "w"){|file| file.puts}
454
- `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt`
455
- end
456
- sleep refresh.to_i
457
- end
458
- end
459
-
460
- end
461
-
462
-
463
- def self.code_runner_execute(ruby_fragment, copts={})
464
- #eval(ruby_fragment, GLOBAL_BINDING)
465
- eval(ruby_fragment)
466
- end
467
- def self.execute(ruby_fragment, copts={})
468
- eval(ruby_fragment, GLOBAL_BINDING)
469
- #eval(ruby_fragment)
470
- end
471
- def self.load_file(files, copts={})
472
- process_command_options(copts)
473
- # begin
474
- files.split(/\s*,\s*/).each do |file|
475
- # p file
476
- raise ArgumentError.new("#{file} is not a file.") unless File.file? file
477
- load file
478
- end
479
- # rescue
480
- # eval(files)
481
- # end
482
-
483
- end
484
-
485
- def self.parameter_scan(parameter_scan_array_file, copts={})
486
- parameter_scan_array = eval(File.read(parameter_scan_array_file))
487
- # process_copts(copts)
488
- runner = fetch_runner(copts)
489
- skip = true unless copts[:k] == false
490
- folder = Dir.pwd
491
- Log.logf("self.parameter_scan")
492
- # @@runners = {}
493
- @@mutex = Mutex.new
494
- # @runner = new(folder, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X])
495
- @@psppipe = PPipe.new(parameter_scan_array.size + 2, true, controller_refresh: 0.5, redirect: false)
496
- parameter_scan_array.each do |parameter_scan|
497
- @@psppipe.fork do
498
- runner.parameter_scan(parameter_scan, copts[:p][0], skip: skip, nprocs: copts[:n])
499
- end
500
- end
501
- @@psppipe.finish
502
- @@psppipe = nil
503
- end
504
- def self.plot_graph(copts = {})
505
- # process_copts(copts)
506
- runner = fetch_runner(copts)
507
- string_to_eval = copts[:w]
508
- #options = (options and options =~ /\S/) ? eval(options): {}
509
- eputs 'Starting Graph'
510
- kit = runner.graphkit_from_lists(copts[:G], copts[:g])
511
- kit.gnuplot(eval: string_to_eval)
512
- gets
513
- kit.close
514
- end
515
- def self.readout(copts={})
516
- # process_copts(copts)
517
- runner = fetch_runner(copts)
518
- puts runner.readout
519
- end
520
- def self.recheck(id, copts={})
521
- # process_copts(copts)
522
- runner = fetch_runner(copts)
523
- runner.run_list[copts[:R]].recheck
524
- runner.respond_to_requests
525
- end
526
- def self.run_class(copts={})
527
- process_command_options(copts)
528
- copts[:no_update] = true
529
- unless copts[:C]
530
- if FileTest.exist? file=Dir.pwd + '/.code_runner_script_defaults.rb'
531
- copts[:C] = eval(File.read(file))[:code]
532
- copts[:m] = eval(File.read(file))[:modlet]
533
- elsif self.runner
534
- copts[:C] = self.runner.code
535
- copts[:m] = self.runner.modlet
536
- end
537
- end
538
- #ep ['code', 'modlet is', copts[:C], copts[:m]]
539
-
540
- return setup_run_class(copts[:C], modlet: copts[:m])
541
- end
542
- def self.code_command(string, copts = {})
543
- run_class(copts).class_eval(string)
544
-
545
- # runner = fetch_runner(copts)
546
- # runner.run_class.class_eval(string)
547
- end
548
- def self.run_command(string, copts={})
549
- # process_copts(copts)
550
- runner = fetch_runner(copts)
551
-
552
- eputs "Calling run_commmand..."
553
- # puts "Warning: Use large cache is on (-U or -u) -- no results will be saved" if runner.use_large_cache
554
- ppipe = PPipe.new(runner.filtered_ids.size + 1, false) if copts[:M]
555
- no_save = (runner.class == RemoteCodeRunner or copts[:y] =~ /no-save/)
556
- # runner.generate_combined_ids
557
- # ep runner.filtered_ids
558
- runner.filtered_ids.each do |id|
559
- run = runner.combined_run_list[id]
560
-
561
- if no_save or run.is_component
562
- if copts[:M]
563
- fork{run.instance_eval(string)}
564
- else
565
- run.instance_eval(string)
566
- end
567
- else
568
- if copts[:M]
569
- pn = ppipe.fork do
570
- Dir.chdir(run.directory) do
571
- run.instance_eval(string);
572
- run.save
573
- run.write_results
574
- end
575
- ppipe.i_send(id, Marshal.dump(run), tp: 0)
576
- end
577
- else
578
- Dir.chdir(run.directory){run.instance_eval(string); run.save; run.write_results}
579
- end
580
-
581
- end
582
- end
583
- unless no_save
584
- (runner.filtered_ids.each{|id| runner.run_list[id] = Marshal.load(ppipe.w_recv(id).contents)};ppipe.finish) if copts[:M]
585
- runner.save_large_cache
586
- end
587
-
588
- # Process.waitall
589
- runner.respond_to_requests
590
- end
591
- def self.runner_eval(string, copts = {})
592
- # process_copts(copts)
593
- runner = fetch_runner(copts)
594
-
595
- #ep ['server string is', string]
596
-
597
- return_val = runner.instance_eval(string)
598
-
599
- if copts[:Z]
600
- Kernel.puts(server_dump(return_val))
601
- else
602
- return return_val
603
- end
604
-
605
- end
606
- def self.scan(scan_string, copts={})
607
- # process_copts(copts)
608
- runner = fetch_runner(copts)
609
- runner.simple_scan(scan_string, nprocs: copts[:n], version: copts[:v], skip: copts[:k], parameters: copts[:p][0])
610
- end
611
- def self.submit(copts = {})
612
- # process_copts(copts)
613
- runner = fetch_runner(copts)
614
- # raise "something is already submitting" if FileTest.exist? "submitting"
615
- runs = []
616
- raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
617
- Dir.chdir(copts[:Y]) do
618
-
619
- copts[:p].push nil if copts[:p] == []
620
- # ep copts[:p]; exit
621
- copts[:p].each do |pars|
622
- run = runner.run_class.new(runner)
623
- # p pars
624
- run.update_submission_parameters(pars)
625
- runs.push run
626
- end
627
- # exit
628
- end
629
- runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit])
630
- #puts "Got here"
631
- #exit(0)
632
- end
633
- def self.resubmit(copts = {})
634
- # process_copts(copts)
635
- runner = fetch_runner(copts)
636
- # raise "something is already submitting" if FileTest.exist? "submitting"
637
- runs = []
638
- raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
639
- Dir.chdir(copts[:Y]) do
640
- runs = runner.filtered_ids.map do |id|
641
- eputs id
642
- run = runner.run_list[id].dup
643
-
644
- run.resubmit_id = run.id
645
- if copts[:smart_resubmit_name]
646
- eputs "Smart name"
647
- run.set(:naming_pars, [:resubmit_id])
648
- end
649
- run.update_submission_parameters(copts[:p][0], false)
650
- run.run_name = nil unless copts[:rerun]
651
- run
652
- end
653
- end
654
- #throw(:here)
655
-
656
- runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit], replace_existing: copts[:replace_existing], smart_resubmit_name: copts[:smart_resubmit_name], rerun: copts[:rerun])
657
- end
658
-
659
- # This method allows the straightforward submission of a single command using the batch queue on any system.
660
- def self.submit_command(jid, comm, copts={})
661
- process_command_options(copts)
662
- submitter = Object.new
663
- submitter.instance_variable_set(:@command, comm)
664
- submitter.instance_variable_set(:@jid, jid)
665
- submitter.instance_variable_set(:@nprocs, copts[:n])
666
- submitter.instance_variable_set(:@wall_mins, copts[:W])
667
- submitter.instance_variable_set(:@project, copts[:P])
668
- class << submitter
669
- include CodeRunner::SYSTEM_MODULE
670
- def executable_name
671
- 'custom'
672
- end
673
- def job_identifier
674
- @jid
675
- end
676
- def run_command
677
- @command
678
- end
679
- end
680
- submitter.execute
681
- end
682
-
683
-
684
-
685
- def self.readout(copts={})
686
- runner = fetch_runner(copts)
687
- runner.readout
688
- end
689
- def self.show_values_of(expression, copts={})
690
- runner = fetch_runner(copts)
691
- p runner.filtered_ids.map{|id| runner.combined_run_list[id].instance_eval(expression)}.uniq.sort
692
- end
693
- def self.status_with_comments(copts={})
694
- copts[:with_comments] = true
695
- status(copts)
696
- end
697
- def self.status(copts={})
698
- # process_copts(copts)
699
- runner = fetch_runner(copts)
700
- runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
701
- end
702
- def self.status_loop(copts={})
703
- # process_copts(copts)
704
- runner = fetch_runner(copts)
705
- runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
706
- break_out = false
707
- loop do
708
- old_trap = trap(2){eputs " Terminating loop, please wait..."; break_out = true}
709
- runner.use_large_cache = true
710
- runner.update(false)
711
- (trap(2, old_trap); break) if break_out
712
- runner.recheck_filtered_runs(false)
713
- runner.print_out(nil, with_comments: copts[:with_comments])
714
- trap(2, old_trap)
715
- break if break_out
716
- break if not runner.run_list.values.find do |r|
717
- not [:Complete, :Failed].include? r.status
718
- end
719
- #ep "sleep"
720
- sleep 3
721
- #ep "end sleep"
722
- end
723
- end
724
- def self.write_graph(name, copts={})
725
- # process_copts(copts)
726
- runner = fetch_runner(copts)
727
- eputs 'Starting Graph'
728
- kit = runner.graphkit_from_lists(copts[:G], copts[:g])
729
- #options = copts[:w]
730
- #options = (options and options =~ /\S/) ? eval(options): {}
731
- name = nil unless name =~ /\S/
732
- max = 0
733
- name.sub!(/^\~/, ENV['HOME']) if name
734
- if name and name =~ /%d\./
735
- regex = Regexp.new(Regexp.escape(File.basename(name)).sub(/%d/, '(?<number>\d+)'))
736
- Dir.entries(File.dirname(name)).join("\n").scan(regex) do
737
- max = [max, $~[:number].to_i].max
738
- end
739
- name = name.sub(/%d/, (max + 1).to_s)
740
- end
741
- raise "kit doesn't have a file_name and no filename specified; can't write graph" unless name or (kit.file_name.class == String and kit.file_name =~ /\S/)
742
- Dir.chdir(COMMAND_FOLDER){kit.gnuplot_write((name or kit.file_name), {eval: copts[:w]})}
743
- end
744
- def self.read_default_command_options(copts)
745
- DEFAULT_COMMAND_OPTIONS.each do |key, value|
746
- copts[key] ||= value
747
- end
748
- end
749
- def self.process_command_options(copts)
750
- if copts[:true]
751
- copts[:true].to_s.split(//).each do |letter|
752
- copts[letter.to_sym] = true
753
- end
754
- end
755
- if copts[:false]
756
- copts[:false].to_s.split(//).each do |letter|
757
- copts[letter.to_sym] = false
758
- end
759
- end
760
-
761
- read_default_command_options(copts)
762
- copts.each do |key, value|
763
- copts[LONG_TO_SHORT[key]] = value if LONG_TO_SHORT[key]
764
- end
765
-
766
-
767
- if copts[:j] # j can be a number '65' or list of numbers '65,43,382'
768
- copts[:f]= "#{eval("[#{copts[:j]}]").inspect}.include? id"
769
- end
770
- if copts[:X] and FileTest.exist? copts[:X]
771
- copts[:X] = File.expand_path(copts[:X])
772
- end
773
- if copts[:z]
774
- Log.log_file = Dir.pwd + '/.cr_logfile.txt'
775
- Log.clean_up
776
- else
777
- Log.log_file = nil
778
- end
779
- copts[:F] = (copts[:F].class == Hash ? copts[:F] : (copts[:F].class == String and copts[:F] =~ /\A\{.*\}\Z/) ? eval(copts[:F]) : {})
780
- copts[:G]= [copts[:G]] if copts[:G].kind_of? String
781
- copts[:g]= [copts[:g]] if copts[:g].kind_of? String
782
- # if copts[:p] and copts[:p].class == String # should be a hash or an inspected hash
783
- # copts[:p] = eval(copts[:p])
784
- # end
785
- copts[:p] = [copts[:p]].compact unless copts[:p].class == Array
786
- #for i in 0...copts[:p].size
787
- case copts[:h]
788
- when :c, :component
789
- copts[:h] = :component
790
- when :r, :real
791
- copts[:h] = :real
792
- else
793
- copts[:h] = :real
794
- end
795
-
796
- copts[:Y] ||= DEFAULT_COMMAND_OPTIONS[:Y] if DEFAULT_COMMAND_OPTIONS[:Y]
797
- if copts[:Y] and copts[:Y] =~ /:/
798
- set_class_defaults(copts)
799
- copts[:running_remotely] = true
800
- else
801
- copts[:Y] = copts[:Y].gsub(/~/, ENV['HOME']) if copts[:Y]
802
- Dir.chdir((copts[:Y] or Dir.pwd)) do
803
- set_runner_defaults(copts)
804
- # ep DEFAULT_RUNNER_OPTIONS
805
- end
806
- end
807
- # ep Log.log_file
808
- #copts[:code_copts].each{|k,v| CODE_OPTIONS[k] = v} if copts[:code_copts]
809
- copts.keys.map{|k| k.to_s}.grep(/_options$/).map{|k| k.to_sym}.each do |k|
810
- CODE_OPTIONS[k.to_s.sub('_options','').to_sym] = copts[k]
811
- end
812
-
813
-
814
- end
815
-
816
- CODE_OPTIONS={}
817
-
818
- # Retrieve the runner with the folder (and possibly server) given in copts[:Y]. If no runner has been loaded for that folder, load one.
819
-
820
- def self.fetch_runner(copts={})
821
- # ep copts
392
+ unless ENV['CODE_RUNNER_LAUNCHER'] =~ /serial/
393
+ Thread.new{loop{`cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`; sleep 1}}
394
+
395
+ mutex = Mutex.new
396
+ processes= []
397
+
398
+ Thread.new do
399
+ loop do
400
+ Dir.entries(tl).each do |file|
401
+ next unless file =~ (/(^.*)\.stop/)
402
+ pid = $1
403
+ mutex.synchronize{Process.kill(pid); processes.delete pid}
404
+ end
405
+ sleep refresh.to_i
406
+ end
407
+ end
408
+
409
+ #Dir.chdir(tl) do
410
+ ppid = $$
411
+ loop do
412
+ sleep refresh.to_i while processes.size >= max_queue.to_i
413
+ # processes = []
414
+ Dir.entries(tl).grep(/(^.*)\.start/).each do |file|
415
+ file =~ (/(^.*)\.start/)
416
+ id = $1
417
+ command = ""
418
+ command = File.read tl + '/' + file while command == ""
419
+ pid = fork do
420
+ processes.each do |wpid|
421
+ # Make sure all previously submitted jobs have finished.
422
+ sleep refresh.to_i while %x[ps -e -o pid,ppid].split("\n").grep(Regexp.new("^\\s*#{wpid}\\s+#{ppid}")).size > 0
423
+ end
424
+ #p ["command", command]
425
+ exec(command + "; wait")
426
+ end
427
+ `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt; ps > #{tl}/queue_status.txt`
428
+ mutex.synchronize{processes.push pid}
429
+
430
+ File.open(tl + '/' + id + '.pid', 'w'){|fle| fle.puts pid}
431
+ FileUtils.rm(tl + '/' + file)
432
+
433
+ Thread.new{Process.wait pid; mutex.synchronize{processes.delete pid}}
434
+ end
435
+ # processes.each{|pid| Process.wait pid}
436
+ sleep refresh.to_i
437
+ end
438
+ #end
439
+ #
440
+ else
441
+ loop do
442
+ Dir.entries(tl).grep(/(^.*)\.start/).each do |file|
443
+ file =~ (/(^.*)\.start/)
444
+ id = $1
445
+ command = ""
446
+ command = File.read tl + '/' + file while command == ""
447
+ pid = 12345
448
+ File.open(tl + '/' + id + '.pid', 'w'){|fle| fle.puts pid}
449
+ File.open("#{tl}/queue_status.txt", "w"){|fle| fle.puts pid}
450
+ `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt`
451
+ FileUtils.rm(tl + '/' + file)
452
+ system "#{command} \n\n wait \n\n"
453
+ File.open("#{tl}/queue_status.txt", "w"){|fle| fle.puts}
454
+ `cp #{tl}/queue_status.txt #{tl}/queue_status2.txt`
455
+ end
456
+ sleep refresh.to_i
457
+ end
458
+ end
459
+
460
+ end
461
+
462
+
463
+ def self.code_runner_execute(ruby_fragment, copts={})
464
+ #eval(ruby_fragment, GLOBAL_BINDING)
465
+ eval(ruby_fragment)
466
+ end
467
+ def self.execute(ruby_fragment, copts={})
468
+ eval(ruby_fragment, GLOBAL_BINDING)
469
+ #eval(ruby_fragment)
470
+ end
471
+ def self.load_file(files, copts={})
472
+ process_command_options(copts)
473
+ # begin
474
+ files.split(/\s*,\s*/).each do |file|
475
+ # p file
476
+ raise ArgumentError.new("#{file} is not a file.") unless File.file? file
477
+ load file
478
+ end
479
+ # rescue
480
+ # eval(files)
481
+ # end
482
+
483
+ end
484
+
485
+ def self.parameter_scan(parameter_scan_array_file, copts={})
486
+ parameter_scan_array = eval(File.read(parameter_scan_array_file))
487
+ # process_copts(copts)
488
+ runner = fetch_runner(copts)
489
+ skip = true unless copts[:k] == false
490
+ #_folder = Dir.pwd
491
+ Log.logf("self.parameter_scan")
492
+ # @@runners = {}
493
+ @@mutex = Mutex.new
494
+ # @runner = new(folder, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X])
495
+ @@psppipe = PPipe.new(parameter_scan_array.size + 2, true, controller_refresh: 0.5, redirect: false)
496
+ parameter_scan_array.each do |parameter_scan|
497
+ @@psppipe.fork do
498
+ runner.parameter_scan(parameter_scan, copts[:p][0], skip: skip, nprocs: copts[:n])
499
+ end
500
+ end
501
+ @@psppipe.finish
502
+ @@psppipe = nil
503
+ end
504
+ def self.plot_graph(copts = {})
505
+ # process_copts(copts)
506
+ runner = fetch_runner(copts)
507
+ string_to_eval = copts[:w]
508
+ #options = (options and options =~ /\S/) ? eval(options): {}
509
+ eputs 'Starting Graph'
510
+ kit = runner.graphkit_from_lists(copts[:G], copts[:g])
511
+ kit.gnuplot(eval: string_to_eval)
512
+ gets
513
+ kit.close
514
+ end
515
+ def self.readout(copts={})
516
+ # process_copts(copts)
517
+ runner = fetch_runner(copts)
518
+ puts runner.readout
519
+ end
520
+ def self.recheck(id, copts={})
521
+ # process_copts(copts)
522
+ runner = fetch_runner(copts)
523
+ runner.run_list[copts[:R]].recheck
524
+ runner.respond_to_requests
525
+ end
526
+ def self.run_class(copts={})
527
+ process_command_options(copts)
528
+ copts[:no_update] = true
529
+ unless copts[:C]
530
+ if FileTest.exist? file=Dir.pwd + '/.code_runner_script_defaults.rb'
531
+ copts[:C] = eval(File.read(file))[:code]
532
+ copts[:m] = eval(File.read(file))[:modlet]
533
+ elsif self.runner
534
+ copts[:C] = self.runner.code
535
+ copts[:m] = self.runner.modlet
536
+ end
537
+ end
538
+ #ep ['code', 'modlet is', copts[:C], copts[:m]]
539
+
540
+ return setup_run_class(copts[:C], modlet: copts[:m])
541
+ end
542
+ def self.code_command(string, copts = {})
543
+ run_class(copts).class_eval(string)
544
+
545
+ # runner = fetch_runner(copts)
546
+ # runner.run_class.class_eval(string)
547
+ end
548
+ def self.run_command(string, copts={})
549
+ # process_copts(copts)
550
+ runner = fetch_runner(copts)
551
+
552
+ eputs "Calling run_commmand..."
553
+ # puts "Warning: Use large cache is on (-U or -u) -- no results will be saved" if runner.use_large_cache
554
+ ppipe = PPipe.new(runner.filtered_ids.size + 1, false) if copts[:M]
555
+ no_save = (runner.class == RemoteCodeRunner or copts[:y] =~ /no-save/)
556
+ # runner.generate_combined_ids
557
+ # ep runner.filtered_ids
558
+ runner.filtered_ids.each do |id|
559
+ run = runner.combined_run_list[id]
560
+
561
+ if no_save or run.is_component
562
+ if copts[:M]
563
+ fork{run.instance_eval(string)}
564
+ else
565
+ run.instance_eval(string)
566
+ end
567
+ else
568
+ if copts[:M]
569
+ _pn = ppipe.fork do
570
+ Dir.chdir(run.directory) do
571
+ run.instance_eval(string);
572
+ run.save
573
+ run.write_results
574
+ end
575
+ ppipe.i_send(id, Marshal.dump(run), tp: 0)
576
+ end
577
+ else
578
+ Dir.chdir(run.directory){run.instance_eval(string); run.save; run.write_results}
579
+ end
580
+
581
+ end
582
+ end
583
+ unless no_save
584
+ (runner.filtered_ids.each{|id| runner.run_list[id] = Marshal.load(ppipe.w_recv(id).contents)};ppipe.finish) if copts[:M]
585
+ runner.save_large_cache
586
+ end
587
+
588
+ # Process.waitall
589
+ runner.respond_to_requests
590
+ end
591
+ def self.runner_eval(string, copts = {})
592
+ # process_copts(copts)
593
+ runner = fetch_runner(copts)
594
+
595
+ #ep ['server string is', string]
596
+
597
+ return_val = runner.instance_eval(string)
598
+
599
+ if copts[:Z]
600
+ Kernel.puts(server_dump(return_val))
601
+ else
602
+ return return_val
603
+ end
604
+
605
+ end
606
+ def self.scan(scan_string, copts={})
607
+ # process_copts(copts)
608
+ runner = fetch_runner(copts)
609
+ runner.simple_scan(scan_string, nprocs: copts[:n], version: copts[:v], skip: copts[:k], parameters: copts[:p][0])
610
+ end
611
+ def self.submit(copts = {})
612
+ # process_copts(copts)
613
+ runner = fetch_runner(copts)
614
+ # raise "something is already submitting" if FileTest.exist? "submitting"
615
+ runs = []
616
+ raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
617
+ Dir.chdir(copts[:Y]) do
618
+
619
+ copts[:p].push nil if copts[:p] == []
620
+ # ep copts[:p]; exit
621
+ copts[:p].each do |pars|
622
+ run = runner.run_class.new(runner)
623
+ # p pars
624
+ run.update_submission_parameters(pars)
625
+ runs.push run
626
+ end
627
+ # exit
628
+ end
629
+ runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit])
630
+ #puts "Got here"
631
+ #exit(0)
632
+ end
633
+ def self.resubmit(copts = {})
634
+ # process_copts(copts)
635
+ runner = fetch_runner(copts)
636
+ # raise "something is already submitting" if FileTest.exist? "submitting"
637
+ runs = []
638
+ raise "Parameters must be an array of inspected hashes" unless copts[:p].kind_of? Array
639
+ Dir.chdir(copts[:Y]) do
640
+ runs = runner.filtered_ids.map do |id|
641
+ eputs id
642
+ run = runner.run_list[id].dup
643
+ run.output_file = nil
644
+ run.error_file = nil
645
+
646
+ run.resubmit_id = run.id
647
+ if copts[:smart_resubmit_name]
648
+ eputs "Smart name"
649
+ run.set(:naming_pars, [:resubmit_id])
650
+ end
651
+ run.update_submission_parameters(copts[:p][0], false)
652
+ run.run_name = nil unless copts[:rerun]
653
+ run
654
+ end
655
+ end
656
+ #throw(:here)
657
+
658
+ runner.submit(runs, nprocs: copts[:n], version: copts[:v], skip: copts[:k], job_chain: copts[:J], no_update_before_submit: copts[:no_update_before_submit], replace_existing: copts[:replace_existing], smart_resubmit_name: copts[:smart_resubmit_name], rerun: copts[:rerun])
659
+ end
660
+
661
+ # This method allows the straightforward submission of a single command using the batch queue on any system.
662
+ def self.submit_command(jid, comm, copts={})
663
+ process_command_options(copts)
664
+ submitter = Object.new
665
+ submitter.instance_variable_set(:@command, comm)
666
+ submitter.instance_variable_set(:@jid, jid)
667
+ submitter.instance_variable_set(:@nprocs, copts[:n])
668
+ submitter.instance_variable_set(:@wall_mins, copts[:W])
669
+ submitter.instance_variable_set(:@project, copts[:P])
670
+ class << submitter
671
+ include CodeRunner::SYSTEM_MODULE
672
+ def executable_name
673
+ 'custom'
674
+ end
675
+ def job_identifier
676
+ @jid
677
+ end
678
+ def run_command
679
+ @command
680
+ end
681
+ end
682
+ submitter.execute
683
+ end
684
+
685
+
686
+
687
+ def self.readout(copts={})
688
+ runner = fetch_runner(copts)
689
+ runner.readout
690
+ end
691
+ def self.show_values_of(expression, copts={})
692
+ runner = fetch_runner(copts)
693
+ p runner.filtered_ids.map{|id| runner.combined_run_list[id].instance_eval(expression)}.uniq.sort
694
+ end
695
+ def self.status_with_comments(copts={})
696
+ copts[:with_comments] = true
697
+ status(copts)
698
+ end
699
+ def self.status(copts={})
700
+ # process_copts(copts)
701
+ runner = fetch_runner(copts)
702
+ runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
703
+ end
704
+ def self.status_loop(copts={})
705
+ # process_copts(copts)
706
+ runner = fetch_runner(copts)
707
+ runner.print_out(0, with_comments: copts[:with_comments]) unless copts[:interactive_start] or copts[:Z] or copts[:no_print_out]
708
+ break_out = false
709
+ loop do
710
+ old_trap = trap(2){eputs " Terminating loop, please wait..."; break_out = true}
711
+ runner.use_large_cache = true
712
+ runner.update(false)
713
+ (trap(2, old_trap); break) if break_out
714
+ runner.recheck_filtered_runs(false)
715
+ runner.print_out(nil, with_comments: copts[:with_comments])
716
+ trap(2, old_trap)
717
+ break if break_out
718
+ break if not runner.run_list.values.find do |r|
719
+ not [:Complete, :Failed].include? r.status
720
+ end
721
+ #ep "sleep"
722
+ sleep 3
723
+ #ep "end sleep"
724
+ end
725
+ end
726
+ def self.write_graph(name, copts={})
727
+ # process_copts(copts)
728
+ runner = fetch_runner(copts)
729
+ eputs 'Starting Graph'
730
+ kit = runner.graphkit_from_lists(copts[:G], copts[:g])
731
+ #options = copts[:w]
732
+ #options = (options and options =~ /\S/) ? eval(options): {}
733
+ name = nil unless name =~ /\S/
734
+ max = 0
735
+ name.sub!(/^\~/, ENV['HOME']) if name
736
+ if name and name =~ /%d\./
737
+ regex = Regexp.new(Regexp.escape(File.basename(name)).sub(/%d/, '(?<number>\d+)'))
738
+ Dir.entries(File.dirname(name)).join("\n").scan(regex) do
739
+ max = [max, $~[:number].to_i].max
740
+ end
741
+ name = name.sub(/%d/, (max + 1).to_s)
742
+ end
743
+ raise "kit doesn't have a file_name and no filename specified; can't write graph" unless name or (kit.file_name.class == String and kit.file_name =~ /\S/)
744
+ Dir.chdir(COMMAND_FOLDER){kit.gnuplot_write((name or kit.file_name), {eval: copts[:w]})}
745
+ end
746
+ def self.read_default_command_options(copts)
747
+ DEFAULT_COMMAND_OPTIONS.each do |key, value|
748
+ copts[key] ||= value
749
+ end
750
+ end
751
+ def self.process_command_options(copts)
752
+ if copts[:true]
753
+ copts[:true].to_s.split(//).each do |letter|
754
+ copts[letter.to_sym] = true
755
+ end
756
+ end
757
+ if copts[:false]
758
+ copts[:false].to_s.split(//).each do |letter|
759
+ copts[letter.to_sym] = false
760
+ end
761
+ end
762
+
763
+ read_default_command_options(copts)
764
+ copts.each do |key, value|
765
+ copts[LONG_TO_SHORT[key]] = value if LONG_TO_SHORT[key]
766
+ end
767
+
768
+
769
+ if copts[:j] # j can be a number '65' or list of numbers '65,43,382'
770
+ copts[:f]= "#{eval("[#{copts[:j]}]").inspect}.include? id"
771
+ end
772
+ if copts[:X] and FileTest.exist? copts[:X]
773
+ copts[:X] = File.expand_path(copts[:X])
774
+ end
775
+ if copts[:z]
776
+ Log.log_file = Dir.pwd + '/.cr_logfile.txt'
777
+ Log.clean_up
778
+ else
779
+ Log.log_file = nil
780
+ end
781
+ copts[:F] = (copts[:F].class == Hash ? copts[:F] : (copts[:F].class == String and copts[:F] =~ /\A\{.*\}\Z/) ? eval(copts[:F]) : {})
782
+ copts[:G]= [copts[:G]] if copts[:G].kind_of? String
783
+ copts[:g]= [copts[:g]] if copts[:g].kind_of? String
784
+ # if copts[:p] and copts[:p].class == String # should be a hash or an inspected hash
785
+ # copts[:p] = eval(copts[:p])
786
+ # end
787
+ copts[:p] = [copts[:p]].compact unless copts[:p].class == Array
788
+ #for i in 0...copts[:p].size
789
+ case copts[:h]
790
+ when :c, :component
791
+ copts[:h] = :component
792
+ when :r, :real
793
+ copts[:h] = :real
794
+ else
795
+ copts[:h] = :real
796
+ end
797
+
798
+ copts[:Y] ||= DEFAULT_COMMAND_OPTIONS[:Y] if DEFAULT_COMMAND_OPTIONS[:Y]
799
+ if copts[:Y] and copts[:Y] =~ /:/
800
+ set_class_defaults(copts)
801
+ copts[:running_remotely] = true
802
+ else
803
+ copts[:Y] = copts[:Y].gsub(/~/, ENV['HOME']) if copts[:Y]
804
+ Dir.chdir((copts[:Y] or Dir.pwd)) do
805
+ set_runner_defaults(copts)
806
+ # ep DEFAULT_RUNNER_OPTIONS
807
+ end
808
+ end
809
+ # ep Log.log_file
810
+ #copts[:code_copts].each{|k,v| CODE_OPTIONS[k] = v} if copts[:code_copts]
811
+ copts.keys.map{|k| k.to_s}.grep(/_options$/).map{|k| k.to_sym}.each do |k|
812
+ CODE_OPTIONS[k.to_s.sub('_options','').to_sym] = copts[k]
813
+ end
814
+
815
+
816
+ end
817
+
818
+ CODE_OPTIONS={}
819
+
820
+ # Retrieve the runner with the folder (and possibly server) given in copts[:Y]. If no runner has been loaded for that folder, load one.
821
+
822
+ def self.fetch_runner(copts={})
823
+ # ep copts
822
824
  # If copts(:Y) is an array of locations, return a merged runner of those locations
823
- if copts[:Y].kind_of? Array
824
- runners = copts[:Y].map do |location|
825
- new_copts = copts.dup.absorb(Y: location)
826
- fetch_runner(new_copts)
827
- end
828
- return Merged.new(*runners)
829
- end
830
- process_command_options(copts)
831
- #ep copts
832
- @runners ||= {}
833
- runner = nil
834
- if copts[:Y] and copts[:Y] =~ /:/
835
- copts_r = copts.dup
836
- host, folder = copts[:Y].split(':')
837
- copts_r[:Y] = nil
838
- copts[:Y] = nil
839
- unless @runners[[host, folder]]
840
- copts[:cache] ||= :auto
841
- runner = @runners[[host, folder]] = RemoteCodeRunner.new(host, folder, copts)
842
- #(eputs 'Updating remote...'; runner.update) unless (copts[:g] and (copts[:g].kind_of? String or copts[:g].size > 0)) or copts[:no_update] or copts[:cache]
843
- else
844
- runner = @runners[[host, folder]]
845
- end
846
- runner.process_copts(copts)
847
- else
848
-
849
- copts[:Y] ||= Dir.pwd
850
- Dir.chdir((copts[:Y] or Dir.pwd)) do
851
- unless @runners[copts[:Y]]
852
- runner = @runners[copts[:Y]] = CodeRunner.new(Dir.pwd, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X], defaults_file: copts[:D])
853
- runner.update unless copts[:no_update]
854
- else
855
- runner = @runners[copts[:Y]]
856
- end
857
- #p 'reading defaults', runner.recalc_all, DEFAULT_RUNNER_OPTIONS
858
- runner.read_defaults
859
- #p 'read defaults', runner.recalc_all
860
-
861
- end #Dir.chdir
862
- end
863
- # ep copts
864
- return runner
865
- # @r.read_defaults
866
- end
867
- def self.update_runners
868
- @runners ||= {}
869
- @runners.each{|runner| runner.update}
870
- end
871
-
872
-
873
- def self.runner
874
- @runners ||={}
875
- @runners.values[0]
876
- end
877
-
878
-
879
- def self.manual(copts={})
880
- help = <<EOF
881
-
882
-
825
+ if copts[:Y].kind_of? Array
826
+ runners = copts[:Y].map do |location|
827
+ new_copts = copts.dup.absorb(Y: location)
828
+ fetch_runner(new_copts)
829
+ end
830
+ return Merged.new(*runners)
831
+ end
832
+ process_command_options(copts)
833
+ #ep copts
834
+ @runners ||= {}
835
+ runner = nil
836
+ if copts[:Y] and copts[:Y] =~ /:/
837
+ copts_r = copts.dup
838
+ host, folder = copts[:Y].split(':')
839
+ copts_r[:Y] = nil
840
+ copts[:Y] = nil
841
+ unless @runners[[host, folder]]
842
+ copts[:cache] ||= :auto
843
+ runner = @runners[[host, folder]] = RemoteCodeRunner.new(host, folder, copts)
844
+ #(eputs 'Updating remote...'; runner.update) unless (copts[:g] and (copts[:g].kind_of? String or copts[:g].size > 0)) or copts[:no_update] or copts[:cache]
845
+ else
846
+ runner = @runners[[host, folder]]
847
+ end
848
+ runner.process_copts(copts)
849
+ else
850
+
851
+ copts[:Y] ||= Dir.pwd
852
+ Dir.chdir((copts[:Y] or Dir.pwd)) do
853
+ unless @runners[copts[:Y]]
854
+ runner = @runners[copts[:Y]] = CodeRunner.new(Dir.pwd, code: copts[:C], modlet: copts[:m], version: copts[:v], executable: copts[:X], defaults_file: copts[:D])
855
+ runner.update unless copts[:no_update]
856
+ else
857
+ runner = @runners[copts[:Y]]
858
+ end
859
+ #p 'reading defaults', runner.recalc_all, DEFAULT_RUNNER_OPTIONS
860
+ runner.read_defaults
861
+ #p 'read defaults', runner.recalc_all
862
+
863
+ end #Dir.chdir
864
+ end
865
+ # ep copts
866
+ return runner
867
+ # @r.read_defaults
868
+ end
869
+ def self.update_runners
870
+ @runners ||= {}
871
+ @runners.each{|runner| runner.update}
872
+ end
873
+
874
+
875
+ def self.runner
876
+ @runners ||={}
877
+ @runners.values[0]
878
+ end
879
+
880
+
881
+ def self.manual(copts={})
882
+ help = <<EOF
883
+
884
+
883
885
  -------------CodeRunner Manual---------------
884
886
 
885
887
  Written by Edmund Highcock (2009)
@@ -890,41 +892,41 @@ NAME
890
892
 
891
893
 
892
894
  SYNOPSIS
893
-
895
+
894
896
  coderunner <command> [arguments] [options]
895
897
 
896
898
 
897
899
  DESCRIPTION
898
-
899
- CodeRunner is a framework for the running and analysis of large simulations. It is a Ruby package and can be used to write Ruby scripts. However it also has a powerful command line interface. The aim is to be able to submit simulations, analyse data and plot graphs all using simple commands. This manual is a quick reference. For a more tutorial style introduction to CodeRunner go to
900
+
901
+ CodeRunner is a framework for the running and analysis of large simulations. It is a Ruby package and can be used to write Ruby scripts. However it also has a powerful command line interface. The aim is to be able to submit simulations, analyse data and plot graphs all using simple commands. This manual is a quick reference. For a more tutorial style introduction to CodeRunner go to
900
902
  http://coderunner.sourceforge.net
901
-
902
- This help page documents the commandline interface. For API documentation see
903
+
904
+ This help page documents the commandline interface. For API documentation see
903
905
  http://coderunner.sourceforge.net/api_documentation
904
906
 
905
907
  As is standard, <> indicates a parameter to be supplied, and [] indicates an option, unless otherwise stated.
906
-
908
+
907
909
  EXAMPLES
908
910
 
909
911
  $ coderunner sub -p '{height: 34.2, width: 221}' -n 24x4 -W 300
910
-
912
+
911
913
  $ coderunner can 34 -U
912
-
914
+
913
915
  $ coderunner plot -G 'height:width;{};depth==2.4 and status == :Completed;height'
914
-
916
+
915
917
  $ coderunner st -ul
916
-
918
+
917
919
  $ coderunner rc 'p status' -U
918
920
 
919
921
  COMMANDS
920
922
 
921
923
  Either the long or the short form of the command may be used, except in interactive mode, where only short form can be used.
922
924
 
923
- Long(Short) <Arguments> (Meaningful Options)
925
+ Long(Short) <Arguments> (Meaningful Options)
924
926
  ---------------------------------------------
925
927
 
926
- #{(COMMANDS_WITH_HELP.sort_by{|arr| arr[0]}.map do |arr|
927
- sprintf(" %s %s(%s) \n\t%s", "#{arr[0]}(#{arr[1]})", arr[4].map{|arg| "<#{arg}>"}.join(' ').sub(/(.)$/, '\1 '), arr[5].map{|op| op.to_s}.join(','), arr[3], )
928
+ #{(COMMANDS_WITH_HELP.sort_by{|arr| arr[0]}.map do |arr|
929
+ sprintf(" %s %s(%s) \n\t%s", "#{arr[0]}(#{arr[1]})", arr[4].map{|arg| "<#{arg}>"}.join(' ').sub(/(.)$/, '\1 '), arr[5].map{|op| op.to_s}.join(','), arr[3], )
928
930
  end).join("\n\n")}
929
931
 
930
932
  OPTIONS
@@ -932,16 +934,16 @@ OPTIONS
932
934
  #{((COMMAND_LINE_FLAGS_WITH_HELP + LONG_COMMAND_LINE_OPTIONS).map do |arr|
933
935
  sprintf("%-15s %-2s\n\t%s", arr[0], arr[1], arr[3])
934
936
  end).join("\n\n")
935
- }
937
+ }
936
938
 
937
939
  EOF
938
- #help.gsub(/(.{63,73} |.{73})/){"#$1\n\t"}.paginate
939
- help.paginate
940
- end
940
+ #help.gsub(/(.{63,73} |.{73})/){"#$1\n\t"}.paginate
941
+ help.paginate
942
+ end
943
+
941
944
 
942
945
 
943
946
 
944
-
945
947
 
946
948
  end
947
949