iconPlot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/contrib/nclsh +276 -0
- data/gemspec +19 -0
- data/lib/iconPlot.rb +68 -0
- data/lib/icon_plot.ncl +653 -0
- data/lib/icon_plot_lib.ncl +1687 -0
- data/test/test_iconPlot.rb +33 -0
- metadata +52 -0
data/contrib/nclsh
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
#! /usr/bin/env perl
|
2
|
+
|
3
|
+
=head1 NAME
|
4
|
+
|
5
|
+
=encoding utf8
|
6
|
+
|
7
|
+
nclsh - Wrapper for NCL interpreter providing simplified passing of parameters
|
8
|
+
|
9
|
+
=head1 SYNOPSIS
|
10
|
+
|
11
|
+
B<nclsh> [I<FILE>] [I<OPTION>]... [I<ARG>]...
|
12
|
+
|
13
|
+
=head1 DESCRIPTION
|
14
|
+
|
15
|
+
This is a replacement for calling the NCAR Command Language (NCL) directly
|
16
|
+
whenever you need to pass command line arguments to NCL without twisting your
|
17
|
+
fingers into a knot.
|
18
|
+
|
19
|
+
It simply translates the parameters into a form recognized by NCL, and then
|
20
|
+
runs the B<ncl> command as configured on your system.
|
21
|
+
Within nclsh, ncl is run with the '-n' option,
|
22
|
+
i.e. print output is not prefixed by element indices.
|
23
|
+
|
24
|
+
=head2 Parameter translation
|
25
|
+
|
26
|
+
Any command line parameter is parsed and put into NCL syntax according to
|
27
|
+
these rules:
|
28
|
+
|
29
|
+
=over
|
30
|
+
|
31
|
+
=item *
|
32
|
+
Parameters beginning with '+', '-' or '--' are options.
|
33
|
+
|
34
|
+
=item *
|
35
|
+
Options that are continued with '=' take the remainder of the parameter as
|
36
|
+
value
|
37
|
+
|
38
|
+
=item *
|
39
|
+
Values may be scalar or arrays; array elements are separated by ',' or ':'.
|
40
|
+
|
41
|
+
=item *
|
42
|
+
Values are of type boolean ('True' or 'False', case-insensitive), numeric,
|
43
|
+
or string.
|
44
|
+
|
45
|
+
=item *
|
46
|
+
Options without value are taken to be boolean. Prefix '+' assigns 'False',
|
47
|
+
prefix '-' or '--' assigns 'True'.
|
48
|
+
|
49
|
+
=item *
|
50
|
+
If an option without value begins with '-no' or '--no', and the option name
|
51
|
+
is longer than 2 characters, the leading 'no' is stripped from the option,
|
52
|
+
and its value becomes 'False'.
|
53
|
+
|
54
|
+
=item *
|
55
|
+
The first non-option parameter is taken to be the NCL script file name. Its
|
56
|
+
treatment is described below
|
57
|
+
|
58
|
+
=item *
|
59
|
+
Any remaining non-option parameters are assigned to a string array option
|
60
|
+
named 'ARGS'. Therefore, 'ARGS' is not a valid option name for user options.
|
61
|
+
If there are no such parameters, 'ARGS' is undefined.
|
62
|
+
|
63
|
+
=item *
|
64
|
+
All options are passed to NCL as variable assignment. Variable name is the
|
65
|
+
option name without the '+', '-', '--', or 'no' prefixes. Scalar values are
|
66
|
+
assigned as NCL scalar, array values with NCL array syntax. All non-numeric
|
67
|
+
and non-boolean values are surrounded by NCL's string quote '"'.
|
68
|
+
|
69
|
+
=item *
|
70
|
+
For array assignments, all elements must have the same type. So, if elements
|
71
|
+
are not recognized to be all numeric or all boolean, all elements in that
|
72
|
+
array are interpreted as strings and quoted.
|
73
|
+
|
74
|
+
=back
|
75
|
+
|
76
|
+
Also note that, when calling nclsh, the usual shell restrictions apply when
|
77
|
+
you want to embed white space or meta-characters into your string values.
|
78
|
+
|
79
|
+
=head2 Examples
|
80
|
+
|
81
|
+
nclsh -format=pdf -> ncl format="pdf"
|
82
|
+
nclsh --format=pdf -> ncl format="pdf"
|
83
|
+
nclsh +format=pdf -> ncl format="pdf"
|
84
|
+
nclsh -values=12,34.56,78e9 -> ncl values=(/12,34.56,78e9/)
|
85
|
+
nclsh -variables=slp:sst -> ncl variables=(/"slp","sst"/)
|
86
|
+
nclsh -verbose -> ncl verbose=True
|
87
|
+
nclsh +verbose -> ncl verbose=False
|
88
|
+
nclsh -noverbose -> ncl verbose=False
|
89
|
+
|
90
|
+
I<Please note:>
|
91
|
+
|
92
|
+
nclsh -no -> ncl no=True
|
93
|
+
nclsh +no -> ncl no=False
|
94
|
+
nclsh +noverbose -> ncl noverbose=False
|
95
|
+
nclsh -values=12,True,78e9 -> ncl values=(/"12","True","78e9"/)
|
96
|
+
|
97
|
+
=head2 Script file
|
98
|
+
|
99
|
+
If a NCL script name has been recognized in the parameter list, nclsh checks
|
100
|
+
if the first line of this file contains the she-bang (#!) sequence.
|
101
|
+
If this is the case, the whole script is copied to a temporary file with the
|
102
|
+
first line commented out by NCLs comment character ';'.
|
103
|
+
This allows using nclsh as command script interpreter. The recommended way to
|
104
|
+
do this is heading your NCL script with the following line:
|
105
|
+
|
106
|
+
#! /usr/bin/env nclsh
|
107
|
+
|
108
|
+
Note that, in this case, any error message refers to the temp file name
|
109
|
+
instead of the original script file name. However this should make no
|
110
|
+
difference when using line numbers as only the first line is altered and
|
111
|
+
no lines are deleted or added.
|
112
|
+
|
113
|
+
=head1 SEE ALSO
|
114
|
+
|
115
|
+
The NCL website L<http://www.ncl.ucar.edu/>, providing all you ever wanted to know
|
116
|
+
about NCL, and possibly more.
|
117
|
+
|
118
|
+
=head1 AUTHOR
|
119
|
+
|
120
|
+
Written by Karl-Hermann Wieners, but ultimately inspired by Ralf Müller.
|
121
|
+
|
122
|
+
=head1 COPYRIGHT
|
123
|
+
|
124
|
+
Copyright (c) 2012 Max-Planck-Institut für Meteorologie, Hamburg, Germany
|
125
|
+
|
126
|
+
Copying and distribution of this file, with or without modification,
|
127
|
+
are permitted in any medium without royalty provided the copyright
|
128
|
+
notice and this notice are preserved. This file is offered as-is,
|
129
|
+
without any warranty.
|
130
|
+
|
131
|
+
=cut
|
132
|
+
|
133
|
+
#
|
134
|
+
# $Id: nclsh 216 2012-02-17 20:38:10Z m221078 $
|
135
|
+
#
|
136
|
+
|
137
|
+
use warnings;
|
138
|
+
use strict;
|
139
|
+
|
140
|
+
# Routines for generating safe temp files.
|
141
|
+
use File::Temp qw(tempfile);
|
142
|
+
|
143
|
+
my @args = (); # Non-option arguments (file names etc.)
|
144
|
+
my %opts = (); # Options and their values
|
145
|
+
|
146
|
+
my @params = (); # Parameter list for NCL call
|
147
|
+
my $file; # NCL script file name
|
148
|
+
|
149
|
+
# Parse command line and store results in @args and %opts
|
150
|
+
|
151
|
+
for my $arg (@ARGV) {
|
152
|
+
if($arg =~ /^(\+|--?)(\w+)(=(.*))?$/) {
|
153
|
+
# Anything looking like an option is handled here.
|
154
|
+
# $1 is option prefix, $2 is the option name, $4 are assigned values.
|
155
|
+
# $3 is the optional value assignment (= and values)
|
156
|
+
|
157
|
+
# Special option name ARGS is reserved for passing non-option args.
|
158
|
+
$2 ne 'ARGS' or die("Sorry: option name ARGS is reserved and may not be used!\n");
|
159
|
+
|
160
|
+
if(defined($3)) {
|
161
|
+
# If a value is assigned to the option, store it in %opts.
|
162
|
+
# Make sure that lists (separated by : or ,) are split.
|
163
|
+
my @vals = split(/[,:]/, $4, -1);
|
164
|
+
$opts{$2} = \@vals;
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
# Options w/o assignment are taken to be Boolean.
|
168
|
+
if($1 eq '+') {
|
169
|
+
# Prefix + switches off named option
|
170
|
+
$opts{$2} = [ 'False' ];
|
171
|
+
}
|
172
|
+
elsif(length($2) > 2 && substr($2, 0, 2) eq 'no') {
|
173
|
+
# Prefixes --no... and -no... also denote switched off options.
|
174
|
+
# Option name is set by removing leading 'no' from name.
|
175
|
+
# Bare '-no' is taken as is, i.e. switched on with name 'no'.
|
176
|
+
$opts{substr($2, 2)} = [ 'False' ];
|
177
|
+
}
|
178
|
+
else {
|
179
|
+
# All other cases denote options that are switched on.
|
180
|
+
$opts{$2} = [ 'True' ];
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
else {
|
185
|
+
# Non-option i.e non-prefixed arguments are handled here.
|
186
|
+
|
187
|
+
if(defined($file)) {
|
188
|
+
# All except the first argument are put into the ARGS list
|
189
|
+
push(@args, $arg);
|
190
|
+
}
|
191
|
+
else {
|
192
|
+
# First non-option argument is taken to be the script file
|
193
|
+
$file = $arg;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
# Transform options and arguments to NCL style
|
199
|
+
|
200
|
+
# Transform options to be stored in NCL parameter list
|
201
|
+
while(my ($key, $val) = each(%opts)) {
|
202
|
+
my @vals = @$val;
|
203
|
+
|
204
|
+
# All non-numeric and non-boolean values are considered strings.
|
205
|
+
# If one element in the value list is a string, all are stringified.
|
206
|
+
my $is_boolean = ! grep(!/^(true|false)$/i, @vals);
|
207
|
+
my $is_numeric = ! $is_boolean &&
|
208
|
+
! grep(!/^[+-]?(\d+|\d+\.\d*|\d*\.\d+)([ed][-+]?\d+)?$/i, @vals);
|
209
|
+
my $is_string = ! $is_numeric && ! $is_boolean;
|
210
|
+
|
211
|
+
# Add quotes to string values.
|
212
|
+
if($is_string) {
|
213
|
+
@vals = map { '"'.$_.'"' } @vals;
|
214
|
+
}
|
215
|
+
|
216
|
+
# Capitalize booleans properly
|
217
|
+
if($is_boolean) {
|
218
|
+
@vals = map { uc(substr($_,0,1)).lc(substr($_,1)) } @vals;
|
219
|
+
}
|
220
|
+
|
221
|
+
# Store values into parameter list with option name as variable id.
|
222
|
+
if(@vals == 1) {
|
223
|
+
# Single value options are stored as scalar value.
|
224
|
+
push(@params, $key.'='.$vals[0]);
|
225
|
+
}
|
226
|
+
else {
|
227
|
+
# Multi-valued options are passed as array.
|
228
|
+
push(@params, $key.'=(/'.join(',', @vals).'/)');
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
# Transform non-option args. These are all put into a string array named ARGS.
|
233
|
+
if(@args) {
|
234
|
+
push(@params, 'ARGS=(/'.join(',', map { '"'.$_.'"' } @args).'/)');
|
235
|
+
}
|
236
|
+
|
237
|
+
# Handle the script file
|
238
|
+
|
239
|
+
if(defined($file)) {
|
240
|
+
# Check if first line contains she-bang.
|
241
|
+
# If so, copy contents to a temporary file, disabling first line.
|
242
|
+
# This allows using nclsh as script interpreter, but changes error messages
|
243
|
+
# to contain the temp file name instead of the script file name.
|
244
|
+
|
245
|
+
open(my $file_handle, '<', $file) or die("Sorry: cannot open file: $!\n");
|
246
|
+
if(defined($_ = <$file_handle>) && /^#!/) {
|
247
|
+
# First line is she-bang line.
|
248
|
+
|
249
|
+
# Temp file should be removed at exit.
|
250
|
+
my($temp_handle, $temp_name) = tempfile(UNLINK=>1);
|
251
|
+
# Comment out she-bang line for temp file
|
252
|
+
s/^/\;/;
|
253
|
+
print $temp_handle ($_);
|
254
|
+
# Copy remaining lines into temp file
|
255
|
+
while(<$file_handle>) {
|
256
|
+
print $temp_handle ($_);
|
257
|
+
}
|
258
|
+
push(@params, $temp_name);
|
259
|
+
}
|
260
|
+
else {
|
261
|
+
push(@params, $file);
|
262
|
+
}
|
263
|
+
close($file_handle);
|
264
|
+
}
|
265
|
+
|
266
|
+
# Add option for non-verbose printing within NCL.
|
267
|
+
unshift(@params, '-n');
|
268
|
+
|
269
|
+
# @todo Provide debugging output on demand
|
270
|
+
# while(my ($key, $val) = each(@params)) {
|
271
|
+
# print("$key: '$val'\n");
|
272
|
+
# }
|
273
|
+
|
274
|
+
# Must use system (not exec) to have temp file removed at exit
|
275
|
+
system('ncl', @params);
|
276
|
+
|
data/gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
3
|
+
|
4
|
+
spec = Gem::Specification.new do |s|
|
5
|
+
s.name = "iconPlot"
|
6
|
+
s.version = '0.0.1'
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.files = ["lib/iconPlot.rb"] + ["gemspec"] + ["contrib/nclsh"] + Dir.glob("lib/*ncl")
|
9
|
+
s.test_file = "test/test_iconPlot.rb"
|
10
|
+
s.description = "Plot with ncl via Ruby: requires NCL 6.* and CDO 1.5.*"
|
11
|
+
s.summary = "Plot ICON output with ncl via Ruby"
|
12
|
+
s.author = "Ralf Mueller"
|
13
|
+
s.email = "stark.dreamdetective@gmail.com"
|
14
|
+
s.homepage = "https://github.com/Try2Code/iconPlot"
|
15
|
+
s.license = "GPLv2"
|
16
|
+
s.required_ruby_version = ">= 1.8"
|
17
|
+
end
|
18
|
+
|
19
|
+
# vim:ft=ruby
|
data/lib/iconPlot.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class IconPlot < Struct.new(:caller,:plotter,:libdir,:otype,:display,:cdo,:debug)
|
4
|
+
def IconPlot.gemPath
|
5
|
+
gemSearcher = Gem::GemPathSearcher.new
|
6
|
+
gemspec = gemSearcher.find('iconPlot')
|
7
|
+
gemspec.gem_dir
|
8
|
+
end
|
9
|
+
def initialize(*args)
|
10
|
+
super(*args)
|
11
|
+
|
12
|
+
gempath = IconPlot.gemPath
|
13
|
+
defaults = {
|
14
|
+
:caller => [gempath,'contrib','nclsh'].join(File::SEPARATOR),
|
15
|
+
:plotter => [gempath,'lib','icon_plot.ncl'].join(File::SEPARATOR),
|
16
|
+
:libdir => [gempath,'lib'].join(File::SEPARATOR),
|
17
|
+
:otype => 'png',
|
18
|
+
:display => 'sxiv',
|
19
|
+
:cdo => ENV['CDO'].nil? ? 'cdo' : ENV['CDO'],
|
20
|
+
:debug => false
|
21
|
+
}
|
22
|
+
self.each_pair {|k,v| self[k] = defaults[k] if v.nil? }
|
23
|
+
end
|
24
|
+
def plot(ifile,ofile,varname,vartype='scalar',opts=[])
|
25
|
+
unless File.exists?(ifile)
|
26
|
+
warn "Input file #{ifile} dows NOT exist!"
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
varIdent = case vartype
|
30
|
+
when 'scalar' then "-varName=#{varname}"
|
31
|
+
when 'vector' then "-vecVars=#{varname.split(' ').join(',')}"
|
32
|
+
when 'scatter' then "-plotMode=scatter -vecVars#{varname.split(' ').join(',')}"
|
33
|
+
else
|
34
|
+
warn "Wrong variable type #{vartype}"
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
|
38
|
+
opts[:tStrg] =ofile
|
39
|
+
|
40
|
+
cmd = [self.caller,self.plotter].join(' ')
|
41
|
+
cmd << " -altLibDir=#{self.libdir} #{varIdent} -iFile=#{ifile} -oFile=#{ofile} -oType=#{self.otype} -isIcon -DEBUG"
|
42
|
+
opts.each {|k,v| cmd << " -"<< [k,v].join('=') }
|
43
|
+
puts cmd if self.debug
|
44
|
+
out = IO.popen(cmd).read
|
45
|
+
puts out if self.debug
|
46
|
+
|
47
|
+
return [FileUtils.pwd,"#{ofile}.#{self.otype}"].join(File::SEPARATOR)
|
48
|
+
end
|
49
|
+
def scalarPlot(ifile,ofile,varname,opts={})
|
50
|
+
plot(ifile,ofile,varname,'scalar',opts)
|
51
|
+
end
|
52
|
+
def vectorPlot(ifile,ofile,varname,opts={})
|
53
|
+
plot(ifile,ofile,varname,'vector',opts)
|
54
|
+
end
|
55
|
+
|
56
|
+
def del(file)
|
57
|
+
FileUtils.rm(file) if File.exists?(file)
|
58
|
+
end
|
59
|
+
def show(*files)
|
60
|
+
files.flatten.each {|file| IO.popen("#{self.display} #{file} &") }
|
61
|
+
end
|
62
|
+
def defaultPlot(ifile,ofile,opts={})
|
63
|
+
show(scalarPlot(ifile,ofile,DEFAULT_VARNAME,opts))
|
64
|
+
end
|
65
|
+
def showVector(ifile,ofile,vars,opts={})
|
66
|
+
show(vectorPlot(ifile,ofile,vars,opts))
|
67
|
+
end
|
68
|
+
end
|