line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
2
|
|
|
|
|
|
|
# Geo::ReadGRIB |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# - A Perl extension that gives read access to GRIB "GRIdded Binary" |
5
|
|
|
|
|
|
|
# format Weather data files. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# - Copyright (C) 2006 by Frank Cox |
8
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
package Geo::ReadGRIB; |
11
|
|
|
|
|
|
|
|
12
|
12
|
|
|
12
|
|
305026
|
use 5.006_001; |
|
12
|
|
|
|
|
112
|
|
|
12
|
|
|
|
|
659
|
|
13
|
12
|
|
|
12
|
|
64
|
use strict; |
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
405
|
|
14
|
12
|
|
|
12
|
|
71
|
use warnings; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
369
|
|
15
|
12
|
|
|
12
|
|
17953
|
use IO::File; |
|
12
|
|
|
|
|
166532
|
|
|
12
|
|
|
|
|
2013
|
|
16
|
12
|
|
|
12
|
|
110
|
use Carp; |
|
12
|
|
|
|
|
24
|
|
|
12
|
|
|
|
|
866
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our $VERSION = 1.4; |
19
|
|
|
|
|
|
|
|
20
|
12
|
|
|
12
|
|
8875
|
use Geo::ReadGRIB::PlaceIterator; |
|
12
|
|
|
|
|
29
|
|
|
12
|
|
|
|
|
3597
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $LIB_DIR = "./"; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# try to find wgrib.exe |
25
|
|
|
|
|
|
|
foreach my $inc (@INC) { |
26
|
|
|
|
|
|
|
if ( -e "$inc/Geo/wgrib.exe" ) { |
27
|
|
|
|
|
|
|
$LIB_DIR = "$inc/Geo"; |
28
|
|
|
|
|
|
|
last; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
unless ( -e "$LIB_DIR/wgrib.exe" ) { |
33
|
|
|
|
|
|
|
die "CAN'T CONTINUE: Path to wgrib.exe not found"; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
## Set some signal handlers to clean up temp files in case of interruptions |
37
|
|
|
|
|
|
|
# it does this by calling exit(0) which will run the END block |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
$SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { |
40
|
|
|
|
|
|
|
print "ReadGRIB attempting cleanup...\n"; |
41
|
|
|
|
|
|
|
exit(0); |
42
|
|
|
|
|
|
|
}; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
END { |
45
|
12
|
|
|
12
|
|
20076
|
unlink glob("wgrib.tmp.*"); |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
49
|
|
|
|
|
|
|
# new() |
50
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
51
|
|
|
|
|
|
|
sub new { |
52
|
|
|
|
|
|
|
|
53
|
13
|
|
|
13
|
1
|
16478
|
my $class = shift; |
54
|
13
|
|
|
|
|
43
|
my $gFile = shift; |
55
|
13
|
50
|
|
|
|
93
|
unless ( defined $gFile ) { |
56
|
0
|
|
|
|
|
0
|
croak "new(): Usage: Geo::ReadGRIB->new(GRIB_FILE)"; |
57
|
|
|
|
|
|
|
} |
58
|
13
|
|
|
|
|
291
|
my $self = {}; |
59
|
13
|
|
|
|
|
40
|
bless $self, $class; |
60
|
|
|
|
|
|
|
|
61
|
13
|
|
|
|
|
89
|
$self->{fileName} = $gFile; |
62
|
13
|
|
|
|
|
40
|
$self->{DEBUG} = 0; |
63
|
13
|
|
|
|
|
89
|
$self->backflip( 0 ); |
64
|
|
|
|
|
|
|
|
65
|
13
|
|
|
|
|
63
|
$self->openGrib(); |
66
|
|
|
|
|
|
|
|
67
|
13
|
|
|
|
|
387
|
return $self; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
71
|
|
|
|
|
|
|
# openGrib() |
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
# Open grib file using wgrib.exe and extract header data |
74
|
|
|
|
|
|
|
# |
75
|
|
|
|
|
|
|
# Version 1.0 added a call to _getCatalog() here to get all critical |
76
|
|
|
|
|
|
|
# header data |
77
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
78
|
|
|
|
|
|
|
sub openGrib { |
79
|
|
|
|
|
|
|
|
80
|
12
|
|
|
12
|
|
13236
|
use Time::Local; |
|
12
|
|
|
|
|
31136
|
|
|
12
|
|
|
|
|
31218
|
|
81
|
|
|
|
|
|
|
|
82
|
13
|
|
|
13
|
1
|
27
|
my $self = shift; |
83
|
|
|
|
|
|
|
|
84
|
13
|
|
|
|
|
84
|
my $tmp = $self->tempfile(); |
85
|
13
|
|
|
|
|
108
|
my $cmd = "\"$LIB_DIR\"/wgrib.exe \"$self->{fileName}\" -d 1 -4yr -PDS10 -GDS10 -text -nh -o $tmp"; |
86
|
|
|
|
|
|
|
|
87
|
13
|
|
|
|
|
1294676
|
my $header = qx($cmd); |
88
|
13
|
|
|
|
|
8982
|
unlink $tmp; |
89
|
|
|
|
|
|
|
|
90
|
13
|
50
|
|
|
|
1031
|
if ($?) { |
91
|
0
|
|
|
|
|
0
|
croak "Error in $cmd: $?"; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
13
|
|
|
|
|
1988
|
my @inv = split /:/, $header; |
95
|
|
|
|
|
|
|
|
96
|
13
|
|
|
|
|
113
|
my ( $arg, $val, %head ); |
97
|
|
|
|
|
|
|
|
98
|
13
|
|
|
|
|
218
|
$head{recNum} = $inv[0]; |
99
|
13
|
|
|
|
|
95
|
$head{offset} = $inv[1]; |
100
|
13
|
|
|
|
|
116
|
$head{name} = $inv[3]; |
101
|
13
|
|
|
|
|
112
|
$head{level} = $inv[11]; |
102
|
13
|
|
|
|
|
97
|
$head{fcst} = $inv[12]; |
103
|
|
|
|
|
|
|
|
104
|
13
|
|
|
|
|
567
|
foreach my $invel (@inv) { |
105
|
208
|
|
|
|
|
286
|
chomp $invel; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# print "$invel \n"; |
108
|
208
|
100
|
|
|
|
1550
|
if ( $invel =~ /=/ ) { |
109
|
143
|
|
|
|
|
489
|
( $arg, $val ) = split /=/, $invel; |
110
|
143
|
|
|
|
|
489
|
$val =~ s/^\s+//; |
111
|
143
|
|
|
|
|
836
|
$head{$arg} = $val; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# print " ($arg,$val) \n"; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
13
|
|
|
|
|
400
|
foreach ( sort keys %head ) { |
118
|
|
|
|
|
|
|
# print " $_: $head{$_}\n"; |
119
|
208
|
|
|
|
|
2317
|
$self->{$_} = $head{$_}; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# reduce date string to 'time' format |
124
|
13
|
|
|
|
|
214
|
my ( $yr, $mo, $day, $hr ) = unpack 'A4A2A2A2', $self->{d}; |
125
|
13
|
|
|
|
|
1050
|
$self->{TIME} = timegm( 0, 0, $hr, $day, $mo - 1, $yr - 1900 ); |
126
|
|
|
|
|
|
|
|
127
|
13
|
|
|
|
|
1223
|
$self->{LAST_TIME} = $self->{THIS_TIME} = $self->{TIME}; |
128
|
|
|
|
|
|
|
|
129
|
13
|
|
|
|
|
444
|
$self->parseGDS( $head{GDS10} ); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# if this isn't a lat/long grid we can't go on |
132
|
13
|
50
|
|
|
|
135
|
if ( $self->{GRID_TYPE} != 0 ) { |
133
|
0
|
|
|
|
|
0
|
croak "GDS byte 6 not 0: Only latitude/longitude grids are currently supported"; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
13
|
|
|
|
|
69
|
$self->_getCatalog; |
137
|
|
|
|
|
|
|
|
138
|
13
|
|
|
|
|
1419
|
return; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
142
|
|
|
|
|
|
|
# getCatalogVerbose() DEPRECATED. Use getFullCatalog() instead |
143
|
|
|
|
|
|
|
# |
144
|
|
|
|
|
|
|
# This method is now redundent and just calls getFullCatalog() and sets |
145
|
|
|
|
|
|
|
# an error. |
146
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
147
|
|
|
|
|
|
|
sub getCatalogVerbose { |
148
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
149
|
0
|
|
|
|
|
0
|
$self->error( "Method getCatalogVerbose() DEPRECATED and is now redundant " |
150
|
|
|
|
|
|
|
. "in Geo::ReadGRIB V0.98 and above. Use getFullCatalog() instead" ); |
151
|
0
|
|
|
|
|
0
|
$self->getFullCatalog(); |
152
|
0
|
|
|
|
|
0
|
return 1; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
157
|
|
|
|
|
|
|
# getCatalog( ) DEPRECATED. It now does nothing but set an error. |
158
|
|
|
|
|
|
|
# Do not use in new code and please remove it from old code. |
159
|
|
|
|
|
|
|
# |
160
|
|
|
|
|
|
|
# The catalog is now fetched in openGRIB() and this method dose not need |
161
|
|
|
|
|
|
|
# to be called. |
162
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
163
|
|
|
|
|
|
|
sub getCatalog { |
164
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
165
|
0
|
|
|
|
|
0
|
$self->error( "Method getCatalog DEPRECATED and is no longer needed " |
166
|
|
|
|
|
|
|
. "in Geo::ReadGRIB V1.0 and above" ); |
167
|
0
|
|
|
|
|
0
|
return 1; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
171
|
|
|
|
|
|
|
# _getCatalog() |
172
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
173
|
|
|
|
|
|
|
sub _getCatalog { |
174
|
|
|
|
|
|
|
|
175
|
13
|
|
|
13
|
|
26
|
my $self = shift; |
176
|
|
|
|
|
|
|
|
177
|
13
|
|
|
|
|
265
|
my $tmp = $self->tempfile(); |
178
|
13
|
|
|
|
|
112
|
my $cmd = "\"$LIB_DIR\"/wgrib.exe \"$self->{fileName}\" -o $tmp"; |
179
|
|
|
|
|
|
|
|
180
|
13
|
|
|
|
|
235698
|
my @cat = qx($cmd); |
181
|
13
|
|
|
|
|
2194
|
unlink $tmp; |
182
|
|
|
|
|
|
|
|
183
|
13
|
50
|
|
|
|
582
|
if ($?) { |
184
|
0
|
|
|
|
|
0
|
croak "Error in \$cmd: $?"; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
13
|
|
|
|
|
394
|
my $timeRange = $self->TR; |
188
|
|
|
|
|
|
|
|
189
|
13
|
|
|
|
|
68
|
my ( @line, $offset ); |
190
|
13
|
|
|
|
|
130
|
foreach (@cat) { |
191
|
433
|
|
|
|
|
4334
|
@line = split /:/; |
192
|
433
|
|
|
|
|
1751
|
$line[8] =~ s/P1=//; |
193
|
433
|
|
|
|
|
1158
|
$line[9] =~ s/P2=//; |
194
|
433
|
100
|
|
|
|
1075
|
if ( $timeRange == 0 ) { |
|
|
50
|
|
|
|
|
|
195
|
427
|
|
|
|
|
626
|
$offset = $line[8]; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
elsif ( $timeRange == 10 ) { |
198
|
6
|
|
|
|
|
143
|
$offset = ($line[8] * 256) + $line[9]; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
else { |
201
|
0
|
|
|
|
|
0
|
croak "Time Range flag $timeRange not yet supported. Please ask the Geo::ReadGRIB maintainer to add support for GRIB files like this"; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
433
|
|
|
|
|
1504
|
$offset = $offset * 3600 + $self->{TIME}; |
205
|
433
|
100
|
|
|
|
1339
|
$self->{LAST_TIME} = $offset if $offset > $self->{LAST_TIME}; |
206
|
433
|
|
|
|
|
3961
|
$self->{catalog}->{ $offset }->{ $line[3] } = $line[0]; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
13
|
|
|
|
|
169
|
return; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
213
|
|
|
|
|
|
|
# getFullCatalog() |
214
|
|
|
|
|
|
|
# |
215
|
|
|
|
|
|
|
# recovers the verbose catalog which has text discriptions |
216
|
|
|
|
|
|
|
# of data items. |
217
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
218
|
|
|
|
|
|
|
sub getFullCatalog{ |
219
|
|
|
|
|
|
|
|
220
|
9
|
|
|
9
|
1
|
296
|
my $self = shift; |
221
|
|
|
|
|
|
|
|
222
|
9
|
|
|
|
|
326
|
my $tmp = $self->tempfile(); |
223
|
9
|
|
|
|
|
72
|
my $cmd = "\"$LIB_DIR\"/wgrib.exe -v \"$self->{fileName}\" -o $tmp"; |
224
|
|
|
|
|
|
|
|
225
|
9
|
|
|
|
|
173605
|
my @cat = qx($cmd); |
226
|
9
|
|
|
|
|
1571
|
unlink $tmp; |
227
|
|
|
|
|
|
|
|
228
|
9
|
50
|
|
|
|
523
|
if ($?) { |
229
|
0
|
|
|
|
|
0
|
croak "Error in \$cmd: $?"; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
9
|
|
|
|
|
66
|
my @line; |
233
|
9
|
|
|
|
|
166
|
foreach (@cat) { |
234
|
309
|
|
|
|
|
605
|
chomp; |
235
|
309
|
|
|
|
|
2521
|
@line = split /:/; |
236
|
309
|
|
|
|
|
1309
|
$line[7] =~ s/"//g; |
237
|
309
|
|
|
|
|
1293
|
$self->{v_catalog}->{ $line[3] } = $line[7]; |
238
|
|
|
|
|
|
|
} |
239
|
9
|
|
|
|
|
510
|
return; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
243
|
|
|
|
|
|
|
# parseGDS() |
244
|
|
|
|
|
|
|
# |
245
|
|
|
|
|
|
|
# Assumes gds is dumped in "decimal" (-GDS10) |
246
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
247
|
|
|
|
|
|
|
sub parseGDS { |
248
|
|
|
|
|
|
|
|
249
|
13
|
|
|
13
|
1
|
50
|
my $self = shift; |
250
|
13
|
|
|
|
|
30
|
my $gds = shift; |
251
|
|
|
|
|
|
|
|
252
|
13
|
|
|
|
|
100
|
$gds =~ s/^\s+//; |
253
|
|
|
|
|
|
|
|
254
|
13
|
|
|
|
|
238
|
my @GDS = split /\s+/, $gds; |
255
|
|
|
|
|
|
|
|
256
|
13
|
|
|
|
|
85
|
$self->{GRID_TYPE} = $GDS[5]; |
257
|
|
|
|
|
|
|
|
258
|
13
|
|
|
|
|
50
|
my @slice = @GDS[ 6, 7 ]; |
259
|
13
|
|
|
|
|
158
|
$self->Ni( $self->toDecimal( \@slice ) ); |
260
|
|
|
|
|
|
|
|
261
|
13
|
|
|
|
|
2144
|
@slice = @GDS[ 8, 9 ]; |
262
|
13
|
|
|
|
|
65
|
$self->Nj( $self->toDecimal( \@slice ) ); |
263
|
|
|
|
|
|
|
|
264
|
13
|
|
|
|
|
53
|
@slice = @GDS[ 10, 11, 12 ]; |
265
|
13
|
|
|
|
|
50
|
$self->La1( $self->toDecimal( \@slice ) / 1000 ); |
266
|
|
|
|
|
|
|
|
267
|
13
|
|
|
|
|
55
|
@slice = @GDS[ 13, 14, 15 ]; |
268
|
13
|
|
|
|
|
49
|
$self->Lo1( $self->toDecimal( \@slice ) / 1000 ); |
269
|
|
|
|
|
|
|
|
270
|
13
|
|
|
|
|
124
|
my @rc_flags = split '', sprintf "%08b", $GDS[16]; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# if INCREMENTS_FLAG is true get increments from GDS else calculate |
273
|
13
|
|
|
|
|
88
|
$self->{INCREMENTS_FLAG} = $rc_flags[0]; |
274
|
|
|
|
|
|
|
|
275
|
13
|
|
|
|
|
59
|
@slice = @GDS[ 17, 18, 19 ]; |
276
|
13
|
|
|
|
|
87
|
$self->La2( $self->toDecimal( \@slice ) / 1000 ); |
277
|
|
|
|
|
|
|
|
278
|
13
|
|
|
|
|
115
|
@slice = @GDS[ 20, 21, 22 ]; |
279
|
13
|
|
|
|
|
69
|
$self->Lo2( $self->toDecimal( \@slice ) / 1000 ); |
280
|
|
|
|
|
|
|
|
281
|
13
|
|
|
|
|
47
|
@slice = @GDS[ 23, 24 ]; |
282
|
13
|
50
|
33
|
|
|
258
|
if ( ($slice[0] == $slice[1] and $slice[0] == 255) and not $self->{INCREMENTS_FLAG} ) { |
|
|
|
33
|
|
|
|
|
283
|
0
|
|
|
|
|
0
|
$self->LoInc( $self->calInc( $self->Lo1, $self->Lo2, $self->Ni ) ); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
else { |
286
|
13
|
|
|
|
|
65
|
$self->LoInc( $self->toDecimal( \@slice ) / 1000 ); |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
13
|
|
|
|
|
52
|
@slice = @GDS[ 25, 26 ]; |
290
|
13
|
50
|
33
|
|
|
220
|
if ( ($slice[0] == $slice[1] and $slice[0] == 255) and not $self->{INCREMENTS_FLAG} ) { |
|
|
|
33
|
|
|
|
|
291
|
0
|
|
|
|
|
0
|
$self->LaInc = $self->calInc( $self->La1, $self->La2, $self->Nj ); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
else { |
294
|
13
|
|
|
|
|
56
|
$self->LaInc( $self->toDecimal( \@slice ) / 1000 ); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
13
|
|
|
|
|
110
|
my @scan_mode_flags = split '', sprintf "%08b", $GDS[27]; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# if SN_SCAN_FLAG true data runs in numeric order south-north |
300
|
|
|
|
|
|
|
# elce data runs north-south |
301
|
13
|
|
|
|
|
69
|
$self->sn_scan_flag( $scan_mode_flags[1] ); |
302
|
|
|
|
|
|
|
|
303
|
13
|
50
|
|
|
|
56
|
if ( $scan_mode_flags[0] ) { |
304
|
0
|
|
|
|
|
0
|
croak "Scan mode -i not yet supported. Please contact the Geo::ReadGRIB maintainer to add support for GRIB files that scan east to west"; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
13
|
50
|
|
|
|
50
|
if ( $scan_mode_flags[2] ) { |
308
|
0
|
|
|
|
|
0
|
croak "Scan mode (J,I) not yet supported. Please contact the Geo::ReadGRIB maintainer to add support for GRIB files where adjacent points are consecutive in the j direction (north/south)"; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# Calculate effective Lo where thay are shifted west to 0 degrees. |
312
|
|
|
|
|
|
|
# This will be used for finding data offset and for checking for |
313
|
|
|
|
|
|
|
# out of range args where ranges may cross long 0 |
314
|
13
|
|
|
|
|
43
|
$self->{eLo2} = $self->Lo2; |
315
|
13
|
|
|
|
|
45
|
$self->{eLo1} = $self->Lo2 - ($self->Ni -1) * $self->LoInc; |
316
|
13
|
|
|
|
|
50
|
$self->{Lo_SHIFT} = 0 - $self->{eLo1}; |
317
|
|
|
|
|
|
|
|
318
|
13
|
|
|
|
|
87
|
return; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
322
|
|
|
|
|
|
|
# sn_scan_flag( [flag] ) - getter/setter |
323
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
324
|
|
|
|
|
|
|
sub sn_scan_flag { |
325
|
1335
|
|
|
1335
|
1
|
2485
|
my ( $self, $flag ) = @_; |
326
|
1335
|
100
|
|
|
|
3291
|
$self->{SN_SCAN_FLAG} = $flag if defined $flag; |
327
|
1335
|
|
|
|
|
4719
|
return $self->{SN_SCAN_FLAG}; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
331
|
|
|
|
|
|
|
# error( [error message] ) - getter/setter for errors |
332
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
333
|
|
|
|
|
|
|
sub error { |
334
|
42
|
|
|
42
|
1
|
141
|
my ( $self, $error ) = @_; |
335
|
42
|
100
|
|
|
|
156
|
$self->{ERROR} = $error if defined $error; |
336
|
42
|
|
|
|
|
409
|
return $self->{ERROR}; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
340
|
|
|
|
|
|
|
# Lo1( [val] ) - Getter/setter for Lo1 |
341
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
342
|
|
|
|
|
|
|
sub Lo1 { |
343
|
103
|
|
|
103
|
1
|
216
|
my ( $self, $flag ) = @_; |
344
|
103
|
100
|
|
|
|
529
|
$self->{Lo1} = $flag if defined $flag; |
345
|
103
|
|
|
|
|
631
|
return $self->{Lo1}; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
349
|
|
|
|
|
|
|
# Lo2( [flag] ) - Getter/setter for Lo2 |
350
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
351
|
|
|
|
|
|
|
sub Lo2 { |
352
|
71
|
|
|
71
|
1
|
151
|
my ( $self, $flag ) = @_; |
353
|
71
|
100
|
|
|
|
251
|
$self->{Lo2} = $flag if defined $flag; |
354
|
71
|
|
|
|
|
275
|
return $self->{Lo2}; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
358
|
|
|
|
|
|
|
# LoInc( [flag] ) - Getter/setter for LoInc |
359
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
360
|
|
|
|
|
|
|
sub LoInc { |
361
|
1315
|
|
|
1315
|
1
|
1774
|
my ( $self, $flag ) = @_; |
362
|
1315
|
100
|
|
|
|
3517
|
$self->{LoInc} = $flag if defined $flag; |
363
|
1315
|
|
|
|
|
3307
|
return $self->{LoInc}; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
367
|
|
|
|
|
|
|
# La1( [flag] ) - Getter/setter for La1 |
368
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
369
|
|
|
|
|
|
|
sub La1 { |
370
|
1334
|
|
|
1334
|
1
|
1901
|
my ( $self, $flag ) = @_; |
371
|
1334
|
100
|
|
|
|
2785
|
$self->{La1} = $flag if defined $flag; |
372
|
1334
|
|
|
|
|
4952
|
return $self->{La1}; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
376
|
|
|
|
|
|
|
# TR( [flag] ) - Getter/setter for TR |
377
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
378
|
|
|
|
|
|
|
sub TR { |
379
|
13
|
|
|
13
|
1
|
94
|
my ( $self, $flag ) = @_; |
380
|
13
|
50
|
|
|
|
209
|
$self->{TR} = $flag if defined $flag; |
381
|
13
|
|
|
|
|
127
|
return $self->{TR}; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
385
|
|
|
|
|
|
|
# La2( [flag] ) - Getter/setter for La2 |
386
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
387
|
|
|
|
|
|
|
sub La2 { |
388
|
58
|
|
|
58
|
1
|
225
|
my ( $self, $flag ) = @_; |
389
|
58
|
100
|
|
|
|
630
|
$self->{La2} = $flag if defined $flag; |
390
|
58
|
|
|
|
|
396
|
return $self->{La2}; |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
394
|
|
|
|
|
|
|
# LaInc( [flag] )- Getter/setter for LaInc |
395
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
396
|
|
|
|
|
|
|
sub LaInc { |
397
|
1937
|
|
|
1937
|
1
|
2718
|
my ( $self, $flag ) = @_; |
398
|
1937
|
100
|
|
|
|
3931
|
$self->{LaInc} = $flag if defined $flag; |
399
|
1937
|
|
|
|
|
9536
|
return $self->{LaInc}; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
403
|
|
|
|
|
|
|
# Ni( [flag] ) - Getter/setter for Ni |
404
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
405
|
|
|
|
|
|
|
sub Ni { |
406
|
1309
|
|
|
1309
|
1
|
1706
|
my ( $self, $flag ) = @_; |
407
|
1309
|
100
|
|
|
|
4112
|
$self->{Ni} = $flag if defined $flag; |
408
|
1309
|
|
|
|
|
5828
|
return $self->{Ni}; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
412
|
|
|
|
|
|
|
# Nj( [flag] ) - Getter/setter for Nj |
413
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
414
|
|
|
|
|
|
|
sub Nj { |
415
|
13
|
|
|
13
|
1
|
31
|
my ( $self, $flag ) = @_; |
416
|
13
|
50
|
|
|
|
127
|
$self->{Nj} = $flag if defined $flag; |
417
|
13
|
|
|
|
|
38
|
return $self->{Nj}; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
421
|
|
|
|
|
|
|
# clearError() |
422
|
|
|
|
|
|
|
# set errors undef |
423
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
424
|
|
|
|
|
|
|
sub clearError { |
425
|
1273
|
|
|
1273
|
1
|
1466
|
my $self = shift; |
426
|
1273
|
|
|
|
|
2911
|
undef $self->{ERROR}; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
431
|
|
|
|
|
|
|
# validLa( lat ) |
432
|
|
|
|
|
|
|
# |
433
|
|
|
|
|
|
|
# check if lats are in range and return true if they arr, else false |
434
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
435
|
|
|
|
|
|
|
sub validLa { |
436
|
|
|
|
|
|
|
|
437
|
27
|
|
|
27
|
1
|
60
|
my $self = shift; |
438
|
27
|
|
|
|
|
56
|
my $lat = shift; |
439
|
|
|
|
|
|
|
|
440
|
27
|
100
|
|
|
|
210
|
if ( $self->sn_scan_flag ) { |
441
|
13
|
100
|
100
|
|
|
103
|
if ( $lat < $self->La1 or $lat > $self->La2 ) { |
442
|
3
|
|
|
|
|
21
|
return 0; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
else { |
446
|
14
|
100
|
66
|
|
|
137
|
if ( $lat > $self->La1 or $lat < $self->La2 ) { |
447
|
2
|
|
|
|
|
9
|
return 0; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
|
452
|
22
|
|
|
|
|
121
|
return 1; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
456
|
|
|
|
|
|
|
# validLo( 1ong ) |
457
|
|
|
|
|
|
|
# |
458
|
|
|
|
|
|
|
# check that longs are in range and return true if they are, else false. |
459
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
460
|
|
|
|
|
|
|
sub validLo { |
461
|
|
|
|
|
|
|
|
462
|
22
|
|
|
22
|
1
|
46
|
my $self = shift; |
463
|
22
|
|
|
|
|
42
|
my $lo = shift; |
464
|
|
|
|
|
|
|
|
465
|
22
|
100
|
|
|
|
66
|
if ( $self->sn_scan_flag ) { |
466
|
10
|
|
|
|
|
34
|
$lo += $self->{Lo_SHIFT}; |
467
|
10
|
50
|
|
|
|
37
|
if ( $lo > 360 ) { |
468
|
0
|
|
|
|
|
0
|
$lo -= 360; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
10
|
|
|
|
|
37
|
$lo /= $self->LoInc; |
472
|
10
|
50
|
33
|
|
|
101
|
if ( $lo < 0 or $lo > $self->Ni ) { |
473
|
0
|
|
|
|
|
0
|
return 0; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
else { |
477
|
12
|
100
|
100
|
|
|
34
|
if ( $lo < $self->Lo1 or $lo > $self->Lo2 ) { |
478
|
2
|
|
|
|
|
13
|
return 0; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
20
|
|
|
|
|
135
|
return 1; |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
486
|
|
|
|
|
|
|
# adjustLong( long ) |
487
|
|
|
|
|
|
|
# |
488
|
|
|
|
|
|
|
# takes a long and returns a effective long adjusted to the shifted grid |
489
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
490
|
|
|
|
|
|
|
sub adjustLong { |
491
|
|
|
|
|
|
|
|
492
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
493
|
0
|
|
|
|
|
0
|
my $l1 = shift; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
497
|
|
|
|
|
|
|
# toDecimal() |
498
|
|
|
|
|
|
|
# |
499
|
|
|
|
|
|
|
# helper method for parseGDS() |
500
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
501
|
|
|
|
|
|
|
sub toDecimal { |
502
|
|
|
|
|
|
|
|
503
|
104
|
|
|
104
|
1
|
151
|
my $self = shift; |
504
|
104
|
|
|
|
|
252
|
my $inArray = shift; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# if the most segnificant bit is one it's negative... |
507
|
104
|
|
|
|
|
411
|
my $isNeg = 0; |
508
|
104
|
100
|
|
|
|
335
|
if ( $$inArray[0] >= 128 ) { |
509
|
6
|
|
|
|
|
36
|
$isNeg = 1; |
510
|
6
|
|
|
|
|
34
|
$$inArray[0] -= 128; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# print "===== " . $$inArray[0] . " -- " . 2**((@$inArray -1) *8) . "\n"; |
514
|
|
|
|
|
|
|
|
515
|
104
|
|
|
|
|
111
|
my ( $result, $m ); |
516
|
104
|
|
|
|
|
320
|
for ( my $i = @$inArray - 1, my $j = 0 ; $i >= 0 ; $i--, $j++ ) { |
517
|
260
|
|
|
|
|
446
|
$m = 2**( $j * 8 ); |
518
|
260
|
|
|
|
|
679
|
$result += $$inArray[$i] * $m; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
104
|
100
|
|
|
|
367
|
$result *= -1 if $isNeg; |
522
|
104
|
|
|
|
|
910
|
return sprintf "%.2d", $result; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
526
|
|
|
|
|
|
|
# dumpit() |
527
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
528
|
|
|
|
|
|
|
sub dumpit { |
529
|
|
|
|
|
|
|
|
530
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
531
|
|
|
|
|
|
|
|
532
|
12
|
|
|
12
|
|
16930
|
use Data::Dumper; |
|
12
|
|
|
|
|
171589
|
|
|
12
|
|
|
|
|
32574
|
|
533
|
0
|
|
|
|
|
0
|
print Dumper($self); |
534
|
0
|
|
|
|
|
0
|
return; |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
538
|
|
|
|
|
|
|
# calInc( cord1, cord2, points) |
539
|
|
|
|
|
|
|
# |
540
|
|
|
|
|
|
|
# finds degrees between grid points given the start and end and |
541
|
|
|
|
|
|
|
# number of points. If one cord is negative South or west long/lat assumed |
542
|
|
|
|
|
|
|
#--------------------------------------------------------------------------# |
543
|
|
|
|
|
|
|
sub calInc { |
544
|
|
|
|
|
|
|
|
545
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
546
|
0
|
|
|
|
|
0
|
my $c1 = shift; |
547
|
0
|
|
|
|
|
0
|
my $c2 = shift; |
548
|
0
|
|
|
|
|
0
|
my $pts = shift; |
549
|
|
|
|
|
|
|
|
550
|
0
|
|
|
|
|
0
|
my $size; |
551
|
0
|
0
|
0
|
|
|
0
|
if ( $pts == 0 ) { |
|
|
0
|
|
|
|
|
|
552
|
0
|
|
|
|
|
0
|
$size = 0; |
553
|
0
|
|
|
|
|
0
|
$self->error( "calInc: \$pts = 0" ); |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
elsif ( $c1 < 0 or $c2 < 0 ) { |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# print "$size = (abs($c1) + abs($c2) +1) / $pts;\n"; |
558
|
0
|
|
|
|
|
0
|
$size = ( abs($c1) + abs($c2) + 1 ) / $pts; |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
else { |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
# print "$size = (abs($c1 - $c2)) / $pts\n"; |
563
|
0
|
|
|
|
|
0
|
$size = ( abs( $c1 - $c2 ) ) / $pts; |
564
|
|
|
|
|
|
|
} |
565
|
0
|
|
|
|
|
0
|
return sprintf "%.2f", $size; |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
569
|
|
|
|
|
|
|
# lalo2offset(lat, long) |
570
|
|
|
|
|
|
|
# |
571
|
|
|
|
|
|
|
# converts long/lat pairs in degrees to grib table offset |
572
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
573
|
|
|
|
|
|
|
sub lalo2offset { |
574
|
|
|
|
|
|
|
|
575
|
1273
|
|
|
1273
|
1
|
336909
|
my $self = shift; |
576
|
1273
|
|
|
|
|
1730
|
my $lat = shift; |
577
|
1273
|
|
|
|
|
1838
|
my $long = shift; |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
|
580
|
1273
|
|
|
|
|
1726
|
my $thislong = 0; |
581
|
|
|
|
|
|
|
|
582
|
1273
|
|
|
|
|
3486
|
$self->clearError; |
583
|
1273
|
|
|
|
|
1332
|
my $out; |
584
|
|
|
|
|
|
|
|
585
|
1273
|
100
|
|
|
|
2722
|
if ( $self->sn_scan_flag ) { |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
# shift long east until Lo1 = 0 and make sure any long |
588
|
|
|
|
|
|
|
# > 360 degrees is moved back into the range of 0 - 360 |
589
|
1216
|
|
|
|
|
2339
|
$thislong = $long + $self->{Lo_SHIFT}; |
590
|
1216
|
50
|
|
|
|
2371
|
if ( $thislong > 360 ) { |
591
|
0
|
|
|
|
|
0
|
$thislong -= 360; |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
1216
|
|
|
|
|
2611
|
$out = ( ( ( $lat - $self->La1 ) / $self->LaInc ) * $self->Ni ) |
595
|
|
|
|
|
|
|
+ ( ($thislong ) / $self->LoInc ); |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
else { |
598
|
57
|
|
|
|
|
149
|
$out = ( ( $self->La1 - $lat ) / $self->LaInc ) * $self->Ni |
599
|
|
|
|
|
|
|
+ ( ($long - $self->Lo1 ) / $self->LoInc ); |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
1273
|
|
|
|
|
30327
|
return sprintf "%.0f", sprintf "%.6f", $out; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
606
|
|
|
|
|
|
|
# $plit = $w->extractLaLo( data_types, lat1, long1, lat2, long2, time ) |
607
|
|
|
|
|
|
|
# |
608
|
|
|
|
|
|
|
# |
609
|
|
|
|
|
|
|
# data_types is a scalar containing a single data type as a string or |
610
|
|
|
|
|
|
|
# an array ref of data type strings. |
611
|
|
|
|
|
|
|
# |
612
|
|
|
|
|
|
|
# Extracts forecast data for a range of locations from (lat1, long1) to |
613
|
|
|
|
|
|
|
# (lat2, long2) for the given data_type and time. |
614
|
|
|
|
|
|
|
# |
615
|
|
|
|
|
|
|
# This will be much faster than repeated calls to extract() because only one |
616
|
|
|
|
|
|
|
# call to wgrib and just one file open are required. |
617
|
|
|
|
|
|
|
# |
618
|
|
|
|
|
|
|
# Returns a Geo::ReadGRIB::PlaceIterator object. |
619
|
|
|
|
|
|
|
# |
620
|
|
|
|
|
|
|
# Data is no longer stored in the current object by default as of version |
621
|
|
|
|
|
|
|
# 1.4. To turn this behavior back on use the backflip() method; |
622
|
|
|
|
|
|
|
# |
623
|
|
|
|
|
|
|
# |
624
|
|
|
|
|
|
|
# require: lat1 >= lat2 and long1 <= long2 - that is, lat1 is north or lat2 |
625
|
|
|
|
|
|
|
# and long1 is west of long2 (or is the same as) |
626
|
|
|
|
|
|
|
# |
627
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
628
|
|
|
|
|
|
|
sub extractLaLo { |
629
|
|
|
|
|
|
|
|
630
|
6
|
|
|
6
|
1
|
67
|
my $self = shift; |
631
|
6
|
|
|
|
|
31
|
my $type_s = shift; |
632
|
6
|
|
|
|
|
19
|
my $lat1 = shift; |
633
|
6
|
|
|
|
|
28
|
my $long1 = shift; |
634
|
6
|
|
|
|
|
19
|
my $lat2 = shift; |
635
|
6
|
|
|
|
|
23
|
my $long2 = shift; |
636
|
6
|
|
|
|
|
109
|
my $time = shift; |
637
|
|
|
|
|
|
|
|
638
|
6
|
100
|
|
|
|
73
|
my $flipBack = $self->backflip() ? 1 : 0; |
639
|
6
|
50
|
|
|
|
58
|
my $DEBUG = $self->{DEBUG} ? 1 : 0; |
640
|
6
|
|
|
|
|
46
|
my $LoInc = $self->LoInc; |
641
|
|
|
|
|
|
|
|
642
|
6
|
|
|
|
|
13
|
my @types; |
643
|
6
|
50
|
|
|
|
176
|
if ( ref $type_s eq 'ARRAY' ) { |
|
|
50
|
|
|
|
|
|
644
|
0
|
|
|
|
|
0
|
push @types, @$type_s; |
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
elsif ( $type_s =~ /\w+/ ) { |
647
|
6
|
|
|
|
|
17
|
push @types, $type_s; |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
else { |
650
|
0
|
|
|
|
|
0
|
$self->error( "ERROR extractLaLo() \$types required" ); |
651
|
0
|
|
|
|
|
0
|
return; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
6
|
|
|
|
|
16
|
my @times = sort keys %{ $self->{catalog} }; |
|
6
|
|
|
|
|
173
|
|
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
# First see that requested values are in range... |
657
|
6
|
|
|
|
|
52
|
my ($lo1, $lo2, $la1, $la2) = ($self->Lo1, $self->Lo2, $self->La1, $self->La2, ); |
658
|
6
|
50
|
33
|
|
|
189
|
if ( not $lat1 >= $lat2 or not $long1 <= $long2 ) { |
659
|
0
|
|
|
|
|
0
|
$self->error( "ERROR extractLaLo() require: lat1 >= lat2 and long1 <= long2" ); |
660
|
0
|
|
|
|
|
0
|
return; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
|
663
|
6
|
50
|
|
|
|
44
|
if ( not defined $time ) { |
664
|
0
|
|
|
|
|
0
|
$self->error( "ERROR extractLaLo() \$time is required " ); |
665
|
0
|
|
|
|
|
0
|
return; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
6
|
50
|
33
|
|
|
115
|
if ( $time < $self->{TIME} or $time > $self->{LAST_TIME} ) { |
669
|
0
|
|
|
|
|
0
|
$self->error( "ERROR extractLaLo() \$time \"$time\" out of range " |
670
|
|
|
|
|
|
|
. scalar gmtime( $times[0] ) . " ($times[0]) to " |
671
|
|
|
|
|
|
|
. scalar gmtime( $times[-1] ) . " ($times[-1])" ); |
672
|
0
|
|
|
|
|
0
|
return; |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
6
|
50
|
33
|
|
|
59
|
if ( not $self->validLa($lat1) or not $self->validLa($lat2) ) { |
676
|
0
|
|
|
|
|
0
|
$self->error( "extractLaLo(): LAT >$lat1 or $lat2< out of range $la1 to $la2" ); |
677
|
0
|
|
|
|
|
0
|
return; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
6
|
50
|
33
|
|
|
42
|
if ( not $self->validLo( $long1 ) or not $self->validLo( $long2 ) ) { |
681
|
0
|
|
|
|
|
0
|
$self->error( "extractLaLo(): LONG: >$long1 or $long2 < out of range $lo1 to $lo2" ); |
682
|
0
|
|
|
|
|
0
|
return; |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
|
685
|
6
|
|
|
|
|
245
|
my $plit = Geo::ReadGRIB::PlaceIterator->new(); |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# if time is given, use nearest time in catalog... |
688
|
6
|
50
|
|
|
|
29
|
if ( defined $time ) { |
689
|
6
|
|
|
|
|
216
|
$self->findNearestTime( $time ); |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
|
692
|
6
|
|
|
|
|
23
|
my ( $dtaLength, $fileDump, $offset, $dump, $record, $lo, $la ); |
693
|
6
|
|
|
|
|
20
|
my $tm = $self->{THIS_TIME}; |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|
696
|
6
|
|
|
|
|
30
|
for my $type ( @types ) { |
697
|
6
|
|
|
|
|
24
|
$record = $self->{catalog}->{$tm}->{$type}; |
698
|
|
|
|
|
|
|
|
699
|
6
|
50
|
|
|
|
323
|
if ( not defined $record ) { |
700
|
0
|
|
|
|
|
0
|
$self->error( "extractLaLo(): Not a valid type: $type" ); |
701
|
0
|
|
|
|
|
0
|
return 1; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
6
|
|
|
|
|
82
|
my $tmp = $self->tempfile(); |
705
|
6
|
|
|
|
|
53
|
my $cmd = "\"$LIB_DIR\"/wgrib.exe \"$self->{fileName}\" -d $record -nh -o $tmp"; |
706
|
6
|
|
|
|
|
200726
|
my $res = qx($cmd); |
707
|
6
|
50
|
|
|
|
651
|
my $F = IO::File->new( $tmp ) or croak "Can't open temp file"; |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
# Make sure first offset is smallest for any scanning order |
710
|
6
|
|
|
|
|
1956
|
my ( $offsetFst, $offsetLst ) = sort {$a <=> $b} ( |
|
6
|
|
|
|
|
57
|
|
711
|
|
|
|
|
|
|
$self->lalo2offset($lat1, $long1), $self->lalo2offset($lat2, $long2) ); |
712
|
6
|
|
|
|
|
32
|
$dtaLength = ($offsetLst - $offsetFst +1) * 4; |
713
|
6
|
|
|
|
|
51
|
seek $F, $offsetFst * 4, 0; |
714
|
6
|
|
|
|
|
13041
|
read $F, $fileDump, $dtaLength; |
715
|
|
|
|
|
|
|
|
716
|
6
|
|
|
|
|
26
|
my ($x, $y); |
717
|
6
|
|
|
|
|
113
|
$dump = ""; |
718
|
6
|
|
|
|
|
114
|
for ( $la = $lat1, $x = 0 ; $la >= $lat2 ; $la -= $self->LaInc, $x++ ) { |
719
|
651
|
|
|
|
|
2709
|
my $num_lo = sprintf "%d", (($long2 - $long1) / $LoInc) +1; |
720
|
651
|
|
|
|
|
1927
|
$offset = $self->lalo2offset( $la, $long1 ) - $offsetFst; |
721
|
651
|
|
|
|
|
3938
|
my @luck = unpack "f*", substr $fileDump, $offset * 4, 4 * $num_lo; |
722
|
651
|
|
|
|
|
1976
|
for ( $lo = $long1, $y = 0 ; $lo <= $long2 ; $lo += $LoInc, $y++ ) { |
723
|
1083
|
|
|
|
|
1444
|
my $dump = shift @luck; |
724
|
1083
|
100
|
|
|
|
5422
|
$dump = defined $dump ? sprintf "%.2f", $dump : 0.00; |
725
|
1083
|
50
|
|
|
|
2474
|
$dump = 0 if $dump eq ''; |
726
|
1083
|
50
|
|
|
|
2718
|
$dump = "UNDEF" if $dump > 999900000000000000000; |
727
|
1083
|
50
|
|
|
|
1855
|
print gmtime($tm) . ": $self->{v_catalog}->{$type} $dump\n" if $DEBUG; |
728
|
1083
|
100
|
|
|
|
3190
|
$self->{data}->{$tm}->{$la}->{$lo}->{$type} = $dump if $flipBack; |
729
|
|
|
|
|
|
|
# TODO look into the negative lats with CMS data |
730
|
|
|
|
|
|
|
# $self->{matrix}->{$tm}->{$type}->[$x]->[$y] = $dump if $la >= 0 and $lo >= 0; |
731
|
1083
|
|
|
|
|
4918
|
$plit->addData( $tm, $la, $lo, $type, $dump ); |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
} |
734
|
6
|
|
|
|
|
204
|
close $F; |
735
|
6
|
|
|
|
|
2996
|
unlink $tmp; |
736
|
6
|
|
|
|
|
499
|
undef $fileDump; |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
|
739
|
6
|
|
|
|
|
505
|
return $plit; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
743
|
|
|
|
|
|
|
# backflip( [flag] ) - Getter/setter for the backflip() state. |
744
|
|
|
|
|
|
|
# |
745
|
|
|
|
|
|
|
# When true, certain older behaviors return. In version 1.4 this is only the |
746
|
|
|
|
|
|
|
# storage in the current object of data extracted by extractLaLo(). |
747
|
|
|
|
|
|
|
# |
748
|
|
|
|
|
|
|
# default false |
749
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
750
|
|
|
|
|
|
|
sub backflip { |
751
|
20
|
|
|
20
|
1
|
1782
|
my ( $self, $flag ) = @_; |
752
|
20
|
100
|
|
|
|
128
|
$self->{backflip} = $flag if defined $flag; |
753
|
20
|
|
|
|
|
186
|
return $self->{backflip}; |
754
|
|
|
|
|
|
|
} |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
#--------------------------------------------------------------------------- |
757
|
|
|
|
|
|
|
# getMatrix({ time => time, type => type }) |
758
|
|
|
|
|
|
|
# |
759
|
|
|
|
|
|
|
# return the array of the extracted region for type and time |
760
|
|
|
|
|
|
|
# POSSIBLE FUTURE FUNCTION |
761
|
|
|
|
|
|
|
#--------------------------------------------------------------------------- |
762
|
|
|
|
|
|
|
#sub getMatrix { |
763
|
|
|
|
|
|
|
# my ( $self, $r ) = @_; |
764
|
|
|
|
|
|
|
# return $self->{matrix}->{ $r->{time} }->{ $r->{type} }; |
765
|
|
|
|
|
|
|
#} |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
768
|
|
|
|
|
|
|
# $plit = extract(data_type, lat, long, [time]) |
769
|
|
|
|
|
|
|
# |
770
|
|
|
|
|
|
|
# Extracts forecast data for given type and location. Ectracts data for all |
771
|
|
|
|
|
|
|
# times in file unless a specific time is given in epoch seconds. |
772
|
|
|
|
|
|
|
# |
773
|
|
|
|
|
|
|
# Returns a Geo::ReadGRIB::PlaceIterator and extracted data is also |
774
|
|
|
|
|
|
|
# retained in the ReadGRIB object. |
775
|
|
|
|
|
|
|
# |
776
|
|
|
|
|
|
|
# type will be one of the data types in the data |
777
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
778
|
|
|
|
|
|
|
sub extract { |
779
|
|
|
|
|
|
|
|
780
|
15
|
|
|
15
|
1
|
14964
|
my $self = shift; |
781
|
15
|
|
|
|
|
54
|
my $type = shift; |
782
|
15
|
|
|
|
|
26
|
my $lat = shift; |
783
|
15
|
|
|
|
|
38
|
my $long = shift; |
784
|
15
|
|
|
|
|
32
|
my $time = shift; |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# First see that requested values are in range... |
787
|
15
|
|
|
|
|
246
|
my ($lo1, $lo2, $la1, $la2) = ($self->Lo1, $self->Lo2, $self->La1, $self->La2, ); |
788
|
15
|
100
|
|
|
|
110
|
if ( not $self->validLa($lat) ) { |
789
|
5
|
|
|
|
|
146
|
$self->error( "extract(): LAT >$lat< out of range $la1 to $la2" ); |
790
|
5
|
|
|
|
|
38
|
return; |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
|
793
|
10
|
100
|
|
|
|
45
|
if ( not $self->validLo($long) ) { |
794
|
2
|
|
|
|
|
34
|
$self->error( "extract(): LONG: >$long< out of range $lo1 to $lo2" ); |
795
|
2
|
|
|
|
|
9
|
return; |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
8
|
|
|
|
|
90
|
my $offset = $self->lalo2offset( $lat, $long ); |
799
|
|
|
|
|
|
|
|
800
|
8
|
50
|
|
|
|
46
|
if ( $offset < 0 ) { |
801
|
0
|
|
|
|
|
0
|
$self->error( "extract(): offset less than zero" ); |
802
|
0
|
|
|
|
|
0
|
return 1; |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
8
|
50
|
|
|
|
29
|
$time = 0 unless defined $time; |
806
|
|
|
|
|
|
|
|
807
|
8
|
50
|
33
|
|
|
175
|
if ( $time != 0 and $time < $self->{TIME} |
|
|
|
33
|
|
|
|
|
808
|
|
|
|
|
|
|
or $time > $self->{LAST_TIME} ) { |
809
|
|
|
|
|
|
|
|
810
|
0
|
|
|
|
|
0
|
my @times = sort keys %{ $self->{catalog} }; |
|
0
|
|
|
|
|
0
|
|
811
|
0
|
|
|
|
|
0
|
$self->error( "ERROR extract() \$time \"$time\" out of range " |
812
|
|
|
|
|
|
|
. scalar gmtime( $times[0] ) . " ($times[0]) to " |
813
|
|
|
|
|
|
|
. scalar gmtime( $times[-1] ) . " ($times[-1])" ); |
814
|
0
|
|
|
|
|
0
|
return 1; |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
# If a time is given find nearest in catalog |
818
|
8
|
50
|
|
|
|
41
|
if ( defined $time ) { |
819
|
8
|
|
|
|
|
125
|
$self->findNearestTime( $time ); |
820
|
|
|
|
|
|
|
} |
821
|
|
|
|
|
|
|
|
822
|
8
|
|
|
|
|
17
|
my ( $record, $cmd, $res, $dump ); |
823
|
|
|
|
|
|
|
|
824
|
8
|
50
|
|
|
|
189
|
unless ( defined $self->{v_catalog}->{$type} ) { |
825
|
0
|
|
|
|
|
0
|
$self->error( "extract() Type not found: $type" ); |
826
|
0
|
|
|
|
|
0
|
return 1; |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
# Give avaiable data for type and offset. |
830
|
|
|
|
|
|
|
# All times returned unless $time is given. |
831
|
|
|
|
|
|
|
# |
832
|
|
|
|
|
|
|
# If record is alredy in $self->{data} use that |
833
|
|
|
|
|
|
|
# else go to disk... |
834
|
|
|
|
|
|
|
|
835
|
8
|
|
|
|
|
357
|
my $plit = Geo::ReadGRIB::PlaceIterator->new(); |
836
|
|
|
|
|
|
|
|
837
|
8
|
|
|
|
|
34
|
$dump = ""; |
838
|
8
|
|
|
|
|
24
|
foreach my $tm ( sort keys %{ $self->{catalog} } ) { |
|
8
|
|
|
|
|
160
|
|
839
|
8
|
50
|
|
|
|
32
|
if ( $time != 0 ) { |
840
|
8
|
|
|
|
|
29
|
$tm = $self->{THIS_TIME}; |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
|
843
|
8
|
|
|
|
|
32
|
$record = $self->{catalog}->{$tm}->{$type}; |
844
|
|
|
|
|
|
|
|
845
|
8
|
50
|
|
|
|
27
|
if ( not defined $record ) { |
846
|
0
|
|
|
|
|
0
|
$self->error( "extract(): Not a valid type: $type" ); |
847
|
0
|
|
|
|
|
0
|
return 1; |
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
|
850
|
8
|
|
|
|
|
124
|
my $tmp = $self->tempfile(); |
851
|
8
|
|
|
|
|
62
|
$cmd = "\"$LIB_DIR\"/wgrib.exe \"$self->{fileName}\" -d $record -nh -o $tmp"; |
852
|
8
|
|
|
|
|
195415
|
$res = qx($cmd); |
853
|
8
|
50
|
|
|
|
281
|
print "$cmd - OFFSET: $offset " . $offset * 4 . " bytes\n" |
854
|
|
|
|
|
|
|
if $self->{DEBUG}; |
855
|
8
|
50
|
|
|
|
779
|
my $F = IO::File->new( "$tmp" ) or croak "Can't open temp file"; |
856
|
8
|
|
|
|
|
3022
|
seek $F, $offset * 4, 0; |
857
|
8
|
|
|
|
|
253
|
read $F, $dump, 4; |
858
|
8
|
|
|
|
|
79
|
$dump = unpack "f", $dump; |
859
|
8
|
|
|
|
|
225
|
$dump = sprintf "%.2f", $dump; |
860
|
8
|
100
|
|
|
|
178
|
$dump = "UNDEF" if $dump > 999900000000000000000; |
861
|
8
|
50
|
|
|
|
60
|
print gmtime($tm) . ": $self->{v_catalog}->{$type} $dump\n" |
862
|
|
|
|
|
|
|
if $self->{DEBUG}; |
863
|
8
|
|
|
|
|
245
|
$self->{data}->{$tm}->{$lat}->{$long}->{$type} = $dump; |
864
|
8
|
|
|
|
|
152
|
$plit->addData( $tm, $lat, $long, $type, $dump ); |
865
|
8
|
|
|
|
|
152
|
close $F; |
866
|
8
|
|
|
|
|
5078
|
unlink $tmp; |
867
|
8
|
50
|
|
|
|
183
|
last if $time != 0; |
868
|
|
|
|
|
|
|
} |
869
|
8
|
|
|
|
|
304
|
return $plit; |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
873
|
|
|
|
|
|
|
# findNearestTime( time ) |
874
|
|
|
|
|
|
|
# |
875
|
|
|
|
|
|
|
# Find nearest time in catalog... |
876
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
877
|
|
|
|
|
|
|
sub findNearestTime { |
878
|
|
|
|
|
|
|
|
879
|
14
|
|
|
14
|
1
|
42
|
my $self = shift; |
880
|
14
|
|
|
|
|
74
|
my $time = shift; |
881
|
|
|
|
|
|
|
|
882
|
14
|
|
|
|
|
34
|
my @times = sort keys %{ $self->{catalog} }; |
|
14
|
|
|
|
|
565
|
|
883
|
|
|
|
|
|
|
|
884
|
14
|
100
|
|
|
|
214
|
if ( 1 == @times ) { |
885
|
7
|
|
|
|
|
37
|
$self->{THIS_TIME} = $times[0]; |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
else { |
888
|
7
|
|
|
|
|
40
|
for ( my $i = 0, my $j = 1 ; $j <= @times ; $i++, $j++ ) { |
889
|
283
|
100
|
66
|
|
|
1788
|
if ( $time >= $times[$i] and $time <= $times[$j] ) { |
890
|
7
|
50
|
|
|
|
32
|
if ( ( $time - $times[$i] ) <= ( $times[$j] - $time ) ) { |
891
|
0
|
|
|
|
|
0
|
$self->{THIS_TIME} = $times[$i]; |
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
else { |
894
|
7
|
|
|
|
|
25
|
$self->{THIS_TIME} = $times[$j]; |
895
|
|
|
|
|
|
|
} |
896
|
7
|
|
|
|
|
214
|
last; |
897
|
|
|
|
|
|
|
} |
898
|
|
|
|
|
|
|
} |
899
|
|
|
|
|
|
|
} |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
903
|
|
|
|
|
|
|
# getDataHash() |
904
|
|
|
|
|
|
|
# |
905
|
|
|
|
|
|
|
# Returns a hash ref with all the data items in the object. |
906
|
|
|
|
|
|
|
# This will be all the data extracted from the GRIB file for |
907
|
|
|
|
|
|
|
# in the life of the object. |
908
|
|
|
|
|
|
|
# |
909
|
|
|
|
|
|
|
# The structure is |
910
|
|
|
|
|
|
|
# |
911
|
|
|
|
|
|
|
# $t->{time}->{lat}->{long}->{type} |
912
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
913
|
|
|
|
|
|
|
sub getDataHash { |
914
|
4
|
|
|
4
|
1
|
12211
|
my $self = shift; |
915
|
4
|
|
|
|
|
23
|
return $self->{data}; |
916
|
|
|
|
|
|
|
} |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
920
|
|
|
|
|
|
|
# clearData( ) |
921
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
922
|
|
|
|
|
|
|
sub clearData { |
923
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
924
|
0
|
|
|
|
|
0
|
undef $self->{data}; |
925
|
0
|
|
|
|
|
0
|
return ; |
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
929
|
|
|
|
|
|
|
# getError() |
930
|
|
|
|
|
|
|
# |
931
|
|
|
|
|
|
|
# returns error string from $self->error |
932
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
933
|
|
|
|
|
|
|
sub getError { |
934
|
28
|
|
|
28
|
1
|
1564
|
my $self = shift; |
935
|
28
|
100
|
|
|
|
225
|
return defined $self->error ? $self->error : undef; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
939
|
|
|
|
|
|
|
# m2ft(meters) |
940
|
|
|
|
|
|
|
# |
941
|
|
|
|
|
|
|
# convert meters to feet |
942
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
943
|
|
|
|
|
|
|
sub m2ft { |
944
|
|
|
|
|
|
|
|
945
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
946
|
0
|
|
|
|
|
0
|
my $m = shift; |
947
|
0
|
|
|
|
|
0
|
return $m * 3.28; |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
951
|
|
|
|
|
|
|
# tempfile() |
952
|
|
|
|
|
|
|
# |
953
|
|
|
|
|
|
|
# return a temp file name |
954
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
955
|
|
|
|
|
|
|
sub tempfile { |
956
|
|
|
|
|
|
|
|
957
|
49
|
|
|
49
|
1
|
117
|
my $self = shift; |
958
|
|
|
|
|
|
|
|
959
|
12
|
|
|
12
|
|
19811
|
use File::Temp qw(:mktemp); |
|
12
|
|
|
|
|
194573
|
|
|
12
|
|
|
|
|
9536
|
|
960
|
|
|
|
|
|
|
|
961
|
49
|
|
|
|
|
792
|
my ( $fh, $fn ) = mkstemp("wgrib.tmp.XXXXXXXXX"); |
962
|
49
|
|
|
|
|
33047
|
return $fn; |
963
|
|
|
|
|
|
|
} |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
966
|
|
|
|
|
|
|
# $p = getParam(parm_name) |
967
|
|
|
|
|
|
|
# |
968
|
|
|
|
|
|
|
# getParam(param_name) returns a scalar with the value of param_name |
969
|
|
|
|
|
|
|
# getParam("show") returns a scalar listing published parameter names. |
970
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
971
|
|
|
|
|
|
|
sub getParam { |
972
|
|
|
|
|
|
|
|
973
|
2
|
|
|
2
|
1
|
953
|
my $self = shift; |
974
|
2
|
|
|
|
|
9
|
my $arg = shift; |
975
|
|
|
|
|
|
|
|
976
|
2
|
|
|
|
|
27
|
my @published = qw/TIME LAST_TIME La1 La2 LaInc Lo1 Lo2 LoInc fileName/; |
977
|
|
|
|
|
|
|
|
978
|
2
|
|
|
|
|
3
|
my $param; |
979
|
2
|
50
|
|
|
|
18
|
if ( defined $arg ) { |
980
|
2
|
100
|
|
|
|
50
|
if ( $arg =~ /show/i ) { |
|
|
50
|
|
|
|
|
|
981
|
1
|
|
|
|
|
7
|
$param = "@published"; |
982
|
|
|
|
|
|
|
} |
983
|
|
|
|
|
|
|
elsif ( grep /$arg/, @published ) { |
984
|
1
|
|
|
|
|
5
|
$param = $self->{$arg}; |
985
|
|
|
|
|
|
|
} |
986
|
|
|
|
|
|
|
else { |
987
|
0
|
|
|
|
|
0
|
$self->error( "getParam(): $arg - Undefined or unpublished parameter" ); |
988
|
0
|
|
|
|
|
0
|
return 1; |
989
|
|
|
|
|
|
|
} |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
else { |
992
|
0
|
|
|
|
|
0
|
$self->error( "getParam(): Usage: getParam(param_name)" ); |
993
|
0
|
|
|
|
|
0
|
return 1; |
994
|
|
|
|
|
|
|
} |
995
|
|
|
|
|
|
|
|
996
|
2
|
|
|
|
|
12
|
return $param; |
997
|
|
|
|
|
|
|
} |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
1000
|
|
|
|
|
|
|
# show() |
1001
|
|
|
|
|
|
|
# |
1002
|
|
|
|
|
|
|
# Returns a scalar containing a string with some selected meta data |
1003
|
|
|
|
|
|
|
# describing the GRIB file. |
1004
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
1005
|
|
|
|
|
|
|
sub show { |
1006
|
|
|
|
|
|
|
|
1007
|
3
|
|
|
3
|
1
|
8146
|
my $self = shift; |
1008
|
3
|
|
|
|
|
14
|
my $arg = shift; |
1009
|
|
|
|
|
|
|
|
1010
|
3
|
|
|
|
|
22
|
my $param; |
1011
|
|
|
|
|
|
|
|
1012
|
3
|
|
|
|
|
66
|
my @published = qw/LAST_TIME La1 La2 LaInc Lo1 Lo2 LoInc TIME fileName/; |
1013
|
|
|
|
|
|
|
|
1014
|
3
|
50
|
|
|
|
40
|
if ( defined $arg ) { |
1015
|
0
|
0
|
|
|
|
0
|
if ( $arg =~ /show/i ) { |
|
|
0
|
|
|
|
|
|
1016
|
0
|
|
|
|
|
0
|
$param = "@published"; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
elsif ( grep /$arg/, @published ) { |
1019
|
0
|
|
|
|
|
0
|
$param = $self->{$arg}; |
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
else { |
1022
|
0
|
|
|
|
|
0
|
$self->error( "show(): $arg - Undefined or unpublished parameter" ); |
1023
|
0
|
|
|
|
|
0
|
return 1; |
1024
|
|
|
|
|
|
|
} |
1025
|
|
|
|
|
|
|
} |
1026
|
|
|
|
|
|
|
else { |
1027
|
3
|
|
|
|
|
13
|
my $types; |
1028
|
3
|
|
|
|
|
13
|
foreach ( sort keys %{ $self->{v_catalog} } ) { |
|
3
|
|
|
|
|
29
|
|
1029
|
3
|
|
|
|
|
36
|
$types .= sprintf "%8s: %s\n", $_, $self->{v_catalog}->{$_}; |
1030
|
|
|
|
|
|
|
} |
1031
|
|
|
|
|
|
|
|
1032
|
3
|
|
|
|
|
12
|
my @times = sort keys %{ $self->{catalog} }; |
|
3
|
|
|
|
|
109
|
|
1033
|
3
|
|
|
|
|
57
|
my $t = scalar gmtime( $times[0] ) . " ($times[0]) to "; |
1034
|
3
|
|
|
|
|
28
|
$t .= scalar gmtime( $times[-1] ) . " ($times[-1])"; |
1035
|
|
|
|
|
|
|
|
1036
|
3
|
|
|
|
|
96
|
$param = <<" PARAM"; |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
Locations: |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
lat: $self->{La1} to $self->{La2} |
1041
|
|
|
|
|
|
|
long: $self->{Lo1} to $self->{Lo2} |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
Times: |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
$t |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
Types: |
1048
|
|
|
|
|
|
|
\n$types |
1049
|
|
|
|
|
|
|
PARAM |
1050
|
|
|
|
|
|
|
} |
1051
|
3
|
|
|
|
|
21
|
return $param; |
1052
|
|
|
|
|
|
|
} |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
1; |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
__DATA__ |