tokfile 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/VERSION +1 -1
- data/bin/tokfile +10 -0
- data/lib/tokfile.rb +111 -0
- data/lib/tokfile/commands.rb +65 -0
- data/lib/tokfile/eqdsk.rb +243 -0
- data/lib/tokfile/ogyropsi.rb +230 -0
- data/test/data/EQDSK +2261 -0
- data/test/data/ogyropsi.dat +11853 -0
- data/test/data/ogyropsi_nobal.dat +11853 -0
- data/test/data/ogyropsi_out.dat +11853 -0
- data/test/test_tokfile.rb +29 -4
- data/tokfile.gemspec +82 -0
- metadata +42 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3683172314a29647ad38abf97453fc714f38b546
|
4
|
+
data.tar.gz: 426fad8bfc5dff6b42dbc3a66b16e1909e1f30ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6479a42f64a2bf13ec6d0e908a8d6760c0ec9808b38d946f2d5d62a5531ebfb11d26342c702c543eddda64b825d6415157465dde38a1aa3adc27ec133bf2243a
|
7
|
+
data.tar.gz: 219c554c4673e79074dd407bd7625a7b0f4a182a7b15034f52632c6772d7f21b428911e5896382becfa308a8a6c86ddbd7baf3a1e59cc669a6caa0990fb47a69
|
data/Gemfile
CHANGED
@@ -2,6 +2,8 @@ source "http://rubygems.org"
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
gem "coderunner", ">= 0.14.13"
|
5
|
+
gem "graphkit", ">= 0.3.3"
|
6
|
+
gem 'command-line-flunky', ">=1.0.0"
|
5
7
|
|
6
8
|
# Add dependencies to develop your gem here.
|
7
9
|
# Include everything needed to run rake, tests, features, etc.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
data/bin/tokfile
ADDED
data/lib/tokfile.rb
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
# A tool for reading, manipulating and converting files containing
|
3
|
+
# tokamak data.
|
4
|
+
|
5
|
+
require 'getoptlong'
|
6
|
+
|
7
|
+
module CommandLineFlunky
|
8
|
+
|
9
|
+
STARTUP_MESSAGE = "\n------Tokamak File Utility (c) Edmund Highcock------"
|
10
|
+
|
11
|
+
MANUAL_HEADER = <<EOF
|
12
|
+
|
13
|
+
-------------Tokamak File Utility Manual---------------
|
14
|
+
|
15
|
+
Written by Edmund Highcock (2014)
|
16
|
+
|
17
|
+
NAME
|
18
|
+
|
19
|
+
tokfile
|
20
|
+
|
21
|
+
|
22
|
+
SYNOPSIS
|
23
|
+
|
24
|
+
tokfile <command> [arguments] [options]
|
25
|
+
|
26
|
+
|
27
|
+
DESCRIPTION
|
28
|
+
|
29
|
+
Convert, manipulate and display files containing tokamak-like data, for example
|
30
|
+
EQDSK, tokamak profile database, iterdb output files from one-two etc.
|
31
|
+
|
32
|
+
EXAMPLES
|
33
|
+
|
34
|
+
$ tokfile convert EQDSK ogyropsi.dat -f eqdsk,ogyropsi
|
35
|
+
|
36
|
+
$ tokfile merge ogyropsi.dat,ogyropsi2.dat ogyropsi3.dat -f ogyropsi -m profiles,geometry
|
37
|
+
|
38
|
+
$ tokfile disp EQDSK -f eqdsk
|
39
|
+
|
40
|
+
|
41
|
+
EOF
|
42
|
+
|
43
|
+
COMMANDS_WITH_HELP = [
|
44
|
+
['convert', 'cv', 2, 'Convert files of one format into another. Not all file formats contain the same information. If information is missing from the input files, a warning will be printed and tokfile will attempt to fill in the gaps using sensible assumptions like Ti/Te = 1. More than one output file can be specified.', ['inputfile', 'outputfile(s)'], [:f, :t]],
|
45
|
+
['display_summary_graph', 'disp', 1, 'Display a summary graph of the file using gnuplot.', ['inputfile',], [:f]],
|
46
|
+
['merge', 'mg', 2, 'Merge data from two input files to create a single output file. ', ['inputfile', 'outputfile(s)'], [:f, :t, :m]],
|
47
|
+
['write_summary_graph', 'wsg', 2, 'Write a summary graph of the file to disk using gnuplot. The file format is determined by the extension of the graph file', ['inputfile', 'graph file'], [:f,:w]],
|
48
|
+
|
49
|
+
]
|
50
|
+
|
51
|
+
SUPPORTED_FORMATS = ['eqdsk', 'ogyropsi']
|
52
|
+
SUPPORTED_MERGE_SOURCES = ['profiles', 'geometry']
|
53
|
+
|
54
|
+
|
55
|
+
COMMAND_LINE_FLAGS_WITH_HELP = [
|
56
|
+
#['--boolean', '-b', GetoptLong::NO_ARGUMENT, 'A boolean option'],
|
57
|
+
['--formats', '-f', GetoptLong::REQUIRED_ARGUMENT, "A list of formats pertaining to the various input and output files (in the order which they appear), separated by commas. If they are all the same, only one value may be given. If a value is left empty (i.e. there are two commas in a row) then the previous value will be used. Currently supported formats are #{SUPPORTED_FORMATS.inspect}. "],
|
58
|
+
['--merge-sources', '-m', GetoptLong::REQUIRED_ARGUMENT, "A list of which bits of information should come from which input file during a merge. Currently supported merge sources are #{SUPPORTED_MERGE_SOURCES.inspect} "],
|
59
|
+
['--modify-graph', '-w', GetoptLong::REQUIRED_ARGUMENT, "A string of Ruby code which is evaluated by the graphkit before the graph is displayed. Can be used for arbitrary manipulation of the graph. E.g. 'self.title=\"A graph\"; self.gp.logscale = \"y\"' "],
|
60
|
+
|
61
|
+
]
|
62
|
+
|
63
|
+
LONG_COMMAND_LINE_OPTIONS = [
|
64
|
+
#["--no-short-form", "", GetoptLong::NO_ARGUMENT, %[This boolean option has no short form]],
|
65
|
+
]
|
66
|
+
|
67
|
+
# specifying flag sets a bool to be true
|
68
|
+
|
69
|
+
CLF_BOOLS = []
|
70
|
+
|
71
|
+
CLF_INVERSE_BOOLS = [] # specifying flag sets a bool to be false
|
72
|
+
|
73
|
+
PROJECT_NAME = 'tokfile'
|
74
|
+
|
75
|
+
def self.method_missing(method, *args)
|
76
|
+
# p method, args
|
77
|
+
TokFile.send(method, *args)
|
78
|
+
end
|
79
|
+
|
80
|
+
#def self.setup(copts)
|
81
|
+
#CommandLineFlunkyTestUtility.setup(copts)
|
82
|
+
#end
|
83
|
+
|
84
|
+
SCRIPT_FILE = __FILE__
|
85
|
+
end
|
86
|
+
|
87
|
+
class TokFile
|
88
|
+
class << self
|
89
|
+
# This function gets called before every command
|
90
|
+
# and allows arbitrary manipulation of the command
|
91
|
+
# options (copts) hash
|
92
|
+
def setup(copts)
|
93
|
+
# None neededed
|
94
|
+
end
|
95
|
+
def verbosity
|
96
|
+
2
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
$has_put_startup_message_for_code_runner = true
|
102
|
+
require 'coderunner'
|
103
|
+
require 'tokfile/commands'
|
104
|
+
require 'tokfile/eqdsk'
|
105
|
+
require 'tokfile/ogyropsi'
|
106
|
+
|
107
|
+
######################################
|
108
|
+
# This must be at the end of the file
|
109
|
+
#
|
110
|
+
require 'command-line-flunky'
|
111
|
+
###############################
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
class TokFile
|
3
|
+
class << self
|
4
|
+
|
5
|
+
#######################################
|
6
|
+
# Class methods that implement commands
|
7
|
+
#######################################
|
8
|
+
|
9
|
+
def display_summary_graph(inputfiles, copts)
|
10
|
+
summary_graphkit(inputfiles, copts).gnuplot
|
11
|
+
end
|
12
|
+
|
13
|
+
def merge(inputfiles, outputfile, copts)
|
14
|
+
inputfiles = inputfiles.split(/,/)
|
15
|
+
formats = copts[:f].split(/,/)
|
16
|
+
formsize = inputfiles.size + 1
|
17
|
+
case formats.size
|
18
|
+
when 1
|
19
|
+
formats = formats * formsize
|
20
|
+
when formsize
|
21
|
+
else
|
22
|
+
raise "Number of formats should be either 1 for all the same or #{formsize}"
|
23
|
+
end
|
24
|
+
raise "Please specify merges as a comma separated list" unless copts[:m].kind_of? String and copts[:m] =~ /,/
|
25
|
+
merges = copts[:m].split(/,/)
|
26
|
+
raise "Please specify the same number of merges as inputfiles" unless merges.size == inputfiles.size
|
27
|
+
output = file_object(outputfile, formats[inputfiles.size] )
|
28
|
+
inputfiles.each_with_index do |file,i|
|
29
|
+
input = file_object(file, formats[i])
|
30
|
+
output.read_data(input, merges[i], copts[:t])
|
31
|
+
end
|
32
|
+
output.write
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_summary_graph(inputfiles, graphname, copts)
|
36
|
+
summary_graphkit(inputfiles, copts).gnuplot_write graphname
|
37
|
+
end
|
38
|
+
|
39
|
+
###############################
|
40
|
+
# Other class methods
|
41
|
+
###############################
|
42
|
+
|
43
|
+
|
44
|
+
def file_object(file, format)
|
45
|
+
case format
|
46
|
+
when 'eqdsk'
|
47
|
+
TokFile::Eqdsk.new(file)
|
48
|
+
when 'ogyropsi'
|
49
|
+
TokFile::Ogyropsi.new(file)
|
50
|
+
else
|
51
|
+
raise "Can't read this file format yet: #{format}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def summary_graphkit(inputfiles, copts)
|
56
|
+
raise 'Only one format allowed for summary_graphkit ' if copts[:f] =~ /,/
|
57
|
+
inputfiles = inputfiles.split(',')
|
58
|
+
kit = inputfiles.map{|inputfile|
|
59
|
+
file_object(inputfile, copts[:f]).summary_graphkit
|
60
|
+
}.inject{|o,n| o.merge(n)}
|
61
|
+
kit.instance_eval(copts[:w]) if copts[:w]
|
62
|
+
kit
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
|
2
|
+
class TokFile::Eqdsk
|
3
|
+
attr_accessor :nrbox, :nzbox
|
4
|
+
#attr_accessor :rboxlen, :zboxlen, :r0exp, :rboxlft
|
5
|
+
DATANAMES = [
|
6
|
+
:rboxlen, :zboxlen, :r0exp, :rboxlft, :dummy,
|
7
|
+
:raxis, :zaxis, :psiaxis, :dummy, :b0exp,
|
8
|
+
:current, :dummy, :dummy, :dummy, :dummy,
|
9
|
+
:dummy, :dummy, :dummy, :dummy, :dummy,
|
10
|
+
:t,
|
11
|
+
:pr,
|
12
|
+
:ttprime,
|
13
|
+
:pprime,
|
14
|
+
:psi,
|
15
|
+
:q,
|
16
|
+
:nbound, :nlimiter,
|
17
|
+
:bound,
|
18
|
+
#:limiter
|
19
|
+
]
|
20
|
+
attr_accessor :rbound, :zbound, :rlimiter, :zlimiter
|
21
|
+
|
22
|
+
require 'scanf'
|
23
|
+
def read(line)
|
24
|
+
#@lines_columns[i] = @lines[i].split(/\s+|(?<=\d)[+-]/).map{|s| eval(s)}
|
25
|
+
line.sub(/\A\s+/, '').sub(/\s+\Z/, '').split(/\s+|(?<=\d)(?=[+-])/).map{|s| eval(s)}
|
26
|
+
#line.scan(/.{15}/).map{|s| eval(s)}
|
27
|
+
|
28
|
+
#ep ['line', line]
|
29
|
+
#arr = []
|
30
|
+
#res = line.scanf("%16.9E"){|n| arr.push n}
|
31
|
+
#line.scanf("%E"){|n| arr.push n[0]}
|
32
|
+
#ep ['res', res, arr]
|
33
|
+
#ep ['res', arr]
|
34
|
+
#arr
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def initialize(file)
|
40
|
+
|
41
|
+
iline = 0
|
42
|
+
counter = 0
|
43
|
+
|
44
|
+
#filehandle = File.open(file, 'r')
|
45
|
+
|
46
|
+
lines = File.read(file).split("\n")
|
47
|
+
#@datastarts = DATANAMES.inject({}){|h, name| h[name] = nil; h}
|
48
|
+
|
49
|
+
#line1 = filehandle.gets
|
50
|
+
#@nrbox, @nzbox = filehandle.gets.split(/\s+/).slice(-2..-1).map{|s| eval(s)}
|
51
|
+
@nrbox, @nzbox = lines[0].split(/\s+/).slice(-2..-1).map{|s| eval(s)}
|
52
|
+
#@rboxlen, @zboxlen, @r0exp, @rboxlft, dummy = read(filehandle.gets)
|
53
|
+
#@raxis, @zaxis, @psiaxis, dummy, @b0exp = read(filehandle.gets)
|
54
|
+
#@current, dummy, dummy, dummy, dummy = read(filehandle.gets)
|
55
|
+
#dummy, dummy, dummy, dummy, dummy = read(filehandle.gets)
|
56
|
+
array = []
|
57
|
+
i = 1
|
58
|
+
vb2 = TokFile.verbosity > 1
|
59
|
+
|
60
|
+
if vb2
|
61
|
+
eputs
|
62
|
+
eputs "Reading data from eqdsk file #{file}."
|
63
|
+
eputs
|
64
|
+
end
|
65
|
+
total_size = 0
|
66
|
+
DATANAMES.each do |name|
|
67
|
+
sz = size(name)
|
68
|
+
total_size += sz
|
69
|
+
#ep ['name', name, 'size', sz]
|
70
|
+
if vb2
|
71
|
+
Terminal.erewind(1)
|
72
|
+
eputs "#{name}(#{sz})#{Terminal::CLEAR_LINE}" if vb2
|
73
|
+
end
|
74
|
+
if array.size < sz
|
75
|
+
#array += read(filehandle.gets)
|
76
|
+
#array += read(lines[i])
|
77
|
+
#i+=1
|
78
|
+
array += read(lines.slice(i...(i+=(sz.to_f/5.0).ceil)).join(' '))
|
79
|
+
#array += lines.slice(i...(i+=(sz.to_f/5.0).ceil)).join(' ')
|
80
|
+
|
81
|
+
#filehandle.gets.scanf("%e"){|scan| array.push scan[0]}
|
82
|
+
end
|
83
|
+
if array.size == sz
|
84
|
+
data = array
|
85
|
+
array = []
|
86
|
+
else
|
87
|
+
data = []
|
88
|
+
while data.size < sz
|
89
|
+
data.push array.shift
|
90
|
+
end
|
91
|
+
end
|
92
|
+
self.class.attr_accessor name
|
93
|
+
case name
|
94
|
+
when :psi
|
95
|
+
set(name, GSL::Matrix.alloc(*data.pieces(@nzbox)).transpose)
|
96
|
+
when :bound
|
97
|
+
data = data.pieces(@nbound).transpose
|
98
|
+
set(:rbound, data[0].to_gslv)
|
99
|
+
set(:zbound, data[1].to_gslv)
|
100
|
+
when :limiter
|
101
|
+
data = data.pieces(@nlimiter).transpose
|
102
|
+
set(:rlimiter, data[0].to_gslv)
|
103
|
+
set(:zlimiter, data[1].to_gslv)
|
104
|
+
else
|
105
|
+
case sz
|
106
|
+
when 1
|
107
|
+
set(name, data[0])
|
108
|
+
else
|
109
|
+
set(name, data.to_gslv)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
@r = GSL::Vector.linspace(@rboxlft, @rboxlft+@rboxlen, @nrbox)
|
114
|
+
@z = GSL::Vector.linspace(-@zboxlen/2.0, @zboxlen/2.0, @nzbox)
|
115
|
+
|
116
|
+
if vb2
|
117
|
+
Terminal.erewind(1)
|
118
|
+
eputs "Read total data size of #{total_size.to_f * 8.0/1.0e6} MB"
|
119
|
+
end
|
120
|
+
|
121
|
+
if TokFile.verbosity > 0
|
122
|
+
eputs <<EOF
|
123
|
+
--------------------------------------
|
124
|
+
Tokfile
|
125
|
+
--------------------------------------
|
126
|
+
Successfully read an eqdsk file called
|
127
|
+
#{file}
|
128
|
+
with the following parameters:
|
129
|
+
|
130
|
+
nrbox = #@nrbox
|
131
|
+
nzbox = #@nzbox
|
132
|
+
nbound = #@nbound
|
133
|
+
raxis = #@raxis
|
134
|
+
--------------------------------------
|
135
|
+
EOF
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
#@lines = File.read(file).split("\n").map{|str| str.sub(/\A\s+/, '').sub(/\s+\Z/, '')}
|
146
|
+
#@nrbox, @nzbox = @lines[0].split(/\s+/).slice(-2..-1).map{|s| eval(s)}
|
147
|
+
#in_data = true; i = 1
|
148
|
+
#@atoms = []
|
149
|
+
#@lines_columns = []
|
150
|
+
#while in_data
|
151
|
+
#@lines_columns[i] = @lines[i].split(/\s+|(?<=\d)[+-]/).map{|s| eval(s)}
|
152
|
+
#@atoms += @lines_columns[i]
|
153
|
+
#if @nbound = @atoms[start(:nbound)]
|
154
|
+
#if @atoms.size > start(:limiter)
|
155
|
+
#in_data = false
|
156
|
+
#end
|
157
|
+
#end
|
158
|
+
#i+=1
|
159
|
+
#end
|
160
|
+
|
161
|
+
#[:t, :p, :pprime, :ttprime, :psi, :q, :rzbound].each do |var|
|
162
|
+
#attr_accessor var
|
163
|
+
#st = start(var)
|
164
|
+
#set(var, @atoms.slice(st...(st+@nrbox))).to_gslv
|
165
|
+
#end
|
166
|
+
|
167
|
+
|
168
|
+
#@rboxlen, @zboxlen, @r0exp, @rboxlft, dummy = @lines_columns[1]
|
169
|
+
#ep ['lines_columns', @lines_columns[1], @lines[1]]
|
170
|
+
|
171
|
+
|
172
|
+
end
|
173
|
+
def summary_graphkit
|
174
|
+
psivec = GSL::Vector.linspace(@psi.min, 0.0, @nrbox)
|
175
|
+
multkit = GraphKit::MultiWindow.new([:pr, :pprime, :t, :ttprime, :q].map{|name|
|
176
|
+
kit = GraphKit.quick_create([psivec, send(name)])
|
177
|
+
kit.title = name.to_s
|
178
|
+
kit.ylabel = nil
|
179
|
+
kit.xlabel = 'psi'
|
180
|
+
kit
|
181
|
+
})
|
182
|
+
psikit = GraphKit.quick_create([@r, @z, @psi])
|
183
|
+
psikit.data[0].gp.with = 'pm3d'
|
184
|
+
psikit.gp.view = "map"
|
185
|
+
boundkit = GraphKit.quick_create([@rbound, @zbound, @rbound.collect{0.0}])
|
186
|
+
psikit += boundkit
|
187
|
+
psikit.gp.key = "off"
|
188
|
+
psikit.title = 'psi'
|
189
|
+
psikit.xlabel = 'R'
|
190
|
+
psikit.ylabel = 'Z'
|
191
|
+
multkit.push psikit
|
192
|
+
multkit.gp.multiplot = "layout 2,3"
|
193
|
+
multkit
|
194
|
+
end
|
195
|
+
def size(var)
|
196
|
+
case var
|
197
|
+
#when :nbound, :nlimiter
|
198
|
+
#1
|
199
|
+
when :bound
|
200
|
+
@nbound * 2
|
201
|
+
when :limiter
|
202
|
+
@nlimiter * 2
|
203
|
+
when :psi
|
204
|
+
@nrbox * @nzbox
|
205
|
+
when :t, :pr, :pprime, :ttprime, :q
|
206
|
+
@nrbox
|
207
|
+
else
|
208
|
+
1
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
#def start(var)
|
213
|
+
#case var
|
214
|
+
#when :t
|
215
|
+
#20
|
216
|
+
#when :p
|
217
|
+
#start(:t) + @nrbox
|
218
|
+
#when :ttprime
|
219
|
+
#start(:p) + @nrbox
|
220
|
+
#when :pprime
|
221
|
+
#start(:ttprime) + @nrbox
|
222
|
+
#when :psi
|
223
|
+
#start(:pprime) + @nrbox
|
224
|
+
#when :q
|
225
|
+
#start(:psi) + @nrbox * @nzbox
|
226
|
+
#when :nbound
|
227
|
+
#start(:q) + @nrbox + 1
|
228
|
+
#when :rzbound
|
229
|
+
#start(:q) + @nrbox + 3
|
230
|
+
#when :limiter
|
231
|
+
#start(:rzbound) + @nbound * 2
|
232
|
+
#else
|
233
|
+
#raise "Start of #{var} unknown"
|
234
|
+
#end
|
235
|
+
#end
|
236
|
+
|
237
|
+
|
238
|
+
#def
|
239
|
+
#def get_int(line, col)
|
240
|
+
#end
|
241
|
+
|
242
|
+
|
243
|
+
end
|