coderunner 0.14.23 → 0.14.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/VERSION +1 -1
- data/coderunner.gemspec +7 -5
- data/lib/coderunner.rb +1 -1
- data/lib/coderunner/class_methods.rb +824 -822
- metadata +78 -50
checksums.yaml
ADDED
@@ -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.
|
1
|
+
0.14.24
|
data/coderunner.gemspec
CHANGED
@@ -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.
|
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-
|
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 = "
|
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 =
|
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"])
|
data/lib/coderunner.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
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
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
#
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
#
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
#
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
#
|
237
|
-
|
238
|
-
#
|
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
|
-
#
|
242
|
-
#
|
243
|
-
#
|
244
|
-
#
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
#
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
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,
|
275
|
-
|
276
|
-
|
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 |
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
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
|
-
|
291
|
-
|
290
|
+
end
|
291
|
+
}
|
292
292
|
end
|
293
293
|
EOF
|
294
|
-
|
295
|
-
#
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
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
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
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
|
-
|
380
|
-
|
381
|
-
|
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
|
-
|
386
|
-
|
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
|
-
|
389
|
+
at_exit{FileUtils.rm_r tl}
|
390
390
|
FileUtils.makedirs tl
|
391
391
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
end
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
#
|
474
|
-
|
475
|
-
#
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
#
|
480
|
-
#
|
481
|
-
#
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
#
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
#
|
493
|
-
|
494
|
-
#
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
#
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
#
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
#
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
#
|
546
|
-
#
|
547
|
-
|
548
|
-
|
549
|
-
#
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
#
|
554
|
-
|
555
|
-
|
556
|
-
#
|
557
|
-
#
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
#
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
#
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
#
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
#
|
613
|
-
|
614
|
-
#
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
#
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
#
|
635
|
-
|
636
|
-
#
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
#
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
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
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
#
|
864
|
-
|
865
|
-
#
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
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
|
-
|
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
|
-
|
939
|
-
|
940
|
-
|
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
|
|