line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Weather::GHCN::Station.pm - class for Station metadata
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
## no critic (Documentation::RequirePodAtEnd)
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Weather::GHCN::Station - class for Station metadata
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 VERSION |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
version v0.0.010 |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use Weather::GHCN::Station;
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
my $stn_obj = Weather::GHCN::Station->new (
|
18
|
|
|
|
|
|
|
id => 'CA006105976',
|
19
|
|
|
|
|
|
|
country => 'CA',
|
20
|
|
|
|
|
|
|
state => 'ON',
|
21
|
|
|
|
|
|
|
active => '1899-2022',
|
22
|
|
|
|
|
|
|
lat => '45.3833',
|
23
|
|
|
|
|
|
|
long => '-75.7167',
|
24
|
|
|
|
|
|
|
elev => 79,
|
25
|
|
|
|
|
|
|
name => 'OTTAWA CDA',
|
26
|
|
|
|
|
|
|
gsn => '',
|
27
|
|
|
|
|
|
|
);
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
The B class is used to encapsulate the metadata for a
|
32
|
|
|
|
|
|
|
station as obtained from the NOAA Global Historical Climatology
|
33
|
|
|
|
|
|
|
Network data repository. Data is sourced from the station list and
|
34
|
|
|
|
|
|
|
the station inventory.
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
The module is primarily for use by Weather::GHCN::Fetch and Weather::GHCN::StationTable.
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=cut
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# these are needed because perlcritic fails to detect that Object::Pad handles these things
|
41
|
|
|
|
|
|
|
## no critic [ValuesAndExpressions::ProhibitVersionStrings]
|
42
|
|
|
|
|
|
|
## no critic [TestingAndDebugging::RequireUseWarnings]
|
43
|
|
|
|
|
|
|
## no critic [References::ProhibitDoubleSigils]
|
44
|
|
|
|
|
|
|
|
45
|
4
|
|
|
4
|
|
3667
|
use v5.18; # minimum for Object::Pad
|
|
4
|
|
|
|
|
21
|
|
46
|
4
|
|
|
4
|
|
585
|
use Object::Pad 0.66 qw( :experimental(init_expr) );
|
|
4
|
|
|
|
|
12150
|
|
|
4
|
|
|
|
|
35
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
package Weather::GHCN::Station;
|
49
|
|
|
|
|
|
|
class Weather::GHCN::Station;
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
our $VERSION = 'v0.0.010'; |
52
|
|
|
|
|
|
|
|
53
|
4
|
|
|
4
|
|
3766
|
use Weather::GHCN::Common qw( rng_new iso_date_time );
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
253
|
|
54
|
4
|
|
|
4
|
|
25
|
use Const::Fast;
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
26
|
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
const my $EMPTY => q(); # empty string
|
57
|
|
|
|
|
|
|
const my $TAB => qq(\t); # tab character
|
58
|
|
|
|
|
|
|
const my $TRUE => 1; # perl's usual TRUE
|
59
|
|
|
|
|
|
|
const my $FALSE => not $TRUE; # a dual-var consisting of '' and 0
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
const my $NOAA_DATA => 'https://www1.ncdc.noaa.gov/pub/data/ghcn/daily/all/';
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# below this value is an error causing stn rejection
|
64
|
|
|
|
|
|
|
const my $ERR_THRESHOLD => 50;
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# attributes
|
67
|
798
|
|
|
798
|
1
|
3657
|
field $id :reader :param; # [0]
|
|
798
|
|
|
|
|
2465
|
|
68
|
1
|
|
|
1
|
1
|
24
|
field $country :reader :param; # [1]
|
|
1
|
|
|
|
|
8
|
|
69
|
1
|
|
|
1
|
1
|
4
|
field $state :reader :param; # [2]
|
|
1
|
|
|
|
|
4
|
|
70
|
7878
|
|
|
7878
|
1
|
76845
|
field $active :mutator :param; # [3]
|
|
7878
|
|
|
|
|
29650
|
|
71
|
5
|
|
|
5
|
1
|
12
|
field $lat :reader :param; # [4]
|
|
5
|
|
|
|
|
68
|
|
72
|
5
|
|
|
5
|
1
|
16
|
field $long :reader :param; # [5]
|
|
5
|
|
|
|
|
24
|
|
73
|
5
|
|
|
5
|
1
|
21
|
field $elev :reader :param; # [6]
|
|
5
|
|
|
|
|
53
|
|
74
|
753
|
|
|
753
|
1
|
1253
|
field $name :reader :param; # [7]
|
|
753
|
|
|
|
|
1968
|
|
75
|
1
|
|
|
1
|
1
|
4
|
field $gsn :reader :param; # [8]
|
|
1
|
|
|
|
|
7
|
|
76
|
3033
|
|
|
3033
|
1
|
7351
|
field $elems_href :reader { {} }; # [9]
|
|
3033
|
|
|
|
|
19565
|
|
77
|
2565
|
|
|
2565
|
1
|
4488
|
field $idx :mutator; # [10]
|
|
2565
|
|
|
|
|
6182
|
|
78
|
7
|
|
|
7
|
1
|
1168
|
field $note_nrs :mutator { rng_new() }; # [11]
|
|
7
|
|
|
|
|
42
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head1 FIELD ACCESSORS
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=over 4
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=item id
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Returns the Station id.
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=item country
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Returns the two-character GEC country code for the station.
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item state
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Returns the two-character state code for US stations, or province code for
|
95
|
|
|
|
|
|
|
Canadian stations.
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item active
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Returns the active range of the station.
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=item lat
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
Returns the station latitude.
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=item long
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Returns the station longitude.
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=item elev
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Returns the station elevation.
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=item name
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Returns the station name.
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=item gsn
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Returns the boolean indicating whether this is a GSN station.
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=item elems_href
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
Returns a hash reference for the measurements available from the
|
124
|
|
|
|
|
|
|
station daily data records.
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=item idx
|
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Returns an index number which is shared by stations that have the
|
129
|
|
|
|
|
|
|
same physical location; i.e. latitude and longitude. When station
|
130
|
|
|
|
|
|
|
instrumentation is changed or there are other significant changes,
|
131
|
|
|
|
|
|
|
a new station id may be assigned. This index enables you to group
|
132
|
|
|
|
|
|
|
together stations that represent the same spot but which may have
|
133
|
|
|
|
|
|
|
different active time periods.
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=item note_nrs
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Returns a number range string that represents notes which are errors
|
138
|
|
|
|
|
|
|
or warnings about the station.
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=back
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=cut
|
143
|
|
|
|
|
|
|
######################################################################
|
144
|
|
|
|
|
|
|
# Class (:common) methods
|
145
|
|
|
|
|
|
|
######################################################################
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head1 CLASS METHODS
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head2 new ()
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
Create a new Station object.
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=head2 Headings ()
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Column headings may be needed prior to creating any Station instances,
|
157
|
|
|
|
|
|
|
for example to print them before any data is loaded. This Headings
|
158
|
|
|
|
|
|
|
class method is provided to handle that situation. There is a
|
159
|
|
|
|
|
|
|
corresponding instance method.
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
If called in list context, a list is return; in scalar context, a
|
162
|
|
|
|
|
|
|
list reference is returned.
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=cut
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
method Headings :common {
|
167
|
|
|
|
|
|
|
my @h = qw(StationId Country State Active Lat Long Elev Location Notes StnIdx Grid );
|
168
|
|
|
|
|
|
|
return wantarray ? @h : \@h;
|
169
|
|
|
|
|
|
|
}
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
######################################################################
|
172
|
|
|
|
|
|
|
# Instance methods
|
173
|
|
|
|
|
|
|
######################################################################
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 INSTANCE METHODS
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 headings
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
See Headings in Class Methods.
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=cut
|
182
|
|
|
|
|
|
|
|
183
|
2
|
|
|
2
|
1
|
1320
|
method headings {
|
184
|
2
|
|
|
|
|
7
|
my @h = Headings;
|
185
|
2
|
100
|
|
|
|
11
|
return wantarray ? @h : \@h;
|
186
|
|
|
|
|
|
|
}
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head2 add_note ($note_id, $msg=undef, $verbose=$FALSE)
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
This method allows you to add numbered notes to each station object.
|
191
|
|
|
|
|
|
|
It is up to the caller to assign meaning to the numbers. They are
|
192
|
|
|
|
|
|
|
stored in a range list (i.e. a Set::IntSpan::Fast object) so that
|
193
|
|
|
|
|
|
|
they can be printed compactly even if there a gaps in the number ranges.
|
194
|
|
|
|
|
|
|
For example, notes 1, 5 and 20 through 25 will print as 1,5,20-25.
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
The message argument is optional, but if you provide a message then
|
197
|
|
|
|
|
|
|
it will be display on STDERR if it is considered an error message.
|
198
|
|
|
|
|
|
|
The threshold is 50 (as established by the hard coded constant
|
199
|
|
|
|
|
|
|
$ERR_THRESHOLD). Anything below that is considered an error. Otherwise
|
200
|
|
|
|
|
|
|
it's considered a warning.
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
When the $VERBOSE argument is true, it causes warnings to also print
|
203
|
|
|
|
|
|
|
to STDERR.
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=cut
|
206
|
|
|
|
|
|
|
|
207
|
3013
|
|
|
3013
|
1
|
38317
|
method add_note ($note_id, $msg=undef, $verbose=$FALSE) {
|
|
3013
|
|
|
|
|
4362
|
|
|
3013
|
|
|
|
|
4779
|
|
|
3013
|
|
|
|
|
4660
|
|
|
3013
|
|
|
|
|
4840
|
|
|
3013
|
|
|
|
|
3801
|
|
208
|
3013
|
|
|
|
|
9225
|
$note_nrs->add_from_string($note_id);
|
209
|
|
|
|
|
|
|
|
210
|
3013
|
100
|
|
|
|
325829
|
return unless $msg;
|
211
|
|
|
|
|
|
|
|
212
|
12
|
100
|
|
|
|
63
|
if ($note_id < $ERR_THRESHOLD) {
|
213
|
2
|
|
|
|
|
8
|
say {*STDERR} '*E* ', $msg;
|
|
2
|
|
|
|
|
80
|
|
214
|
|
|
|
|
|
|
} else {
|
215
|
10
|
100
|
|
|
|
39
|
say {*STDERR} '*W* ', $msg if $verbose;
|
|
1
|
|
|
|
|
6
|
|
216
|
|
|
|
|
|
|
}
|
217
|
|
|
|
|
|
|
|
218
|
12
|
|
|
|
|
58
|
return;
|
219
|
|
|
|
|
|
|
}
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head2 row
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
Returns the station object as a list of field values. The fields
|
224
|
|
|
|
|
|
|
are:
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
$id, $country, $state, $active, $lat, $long, $elev, $name,
|
227
|
|
|
|
|
|
|
$note_text, $idx, $grid>
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
The second last value, $idx is a unique serial index number provided
|
230
|
|
|
|
|
|
|
by GHCH::StationTable during load_stations(). Unless set by a consumer
|
231
|
|
|
|
|
|
|
of this module, its value will be B.
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
The last value, $grid, is a string derived by truncating $lat and
|
234
|
|
|
|
|
|
|
$long to 1 decimal place, converting them to N/S W/E format, and
|
235
|
|
|
|
|
|
|
concatenting them. This results in a box that defines an area within
|
236
|
|
|
|
|
|
|
which there may be other nearby stations of interest.
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
If called in list context, a list is return; in scalar context, a
|
239
|
|
|
|
|
|
|
list reference is returned.
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut
|
242
|
|
|
|
|
|
|
|
243
|
49
|
|
|
49
|
1
|
1146
|
method row {
|
244
|
|
|
|
|
|
|
|
245
|
49
|
100
|
|
|
|
146
|
my $note_text = $note_nrs->cardinality ? '[' . $note_nrs->as_string . ']' : $EMPTY;
|
246
|
|
|
|
|
|
|
|
247
|
49
|
|
|
|
|
2366
|
my @row = (
|
248
|
|
|
|
|
|
|
$id,
|
249
|
|
|
|
|
|
|
$country,
|
250
|
|
|
|
|
|
|
$state,
|
251
|
|
|
|
|
|
|
$active,
|
252
|
|
|
|
|
|
|
$lat,
|
253
|
|
|
|
|
|
|
$long,
|
254
|
|
|
|
|
|
|
$elev,
|
255
|
|
|
|
|
|
|
$name,
|
256
|
|
|
|
|
|
|
$note_text,
|
257
|
|
|
|
|
|
|
$idx,
|
258
|
|
|
|
|
|
|
$self->grid,
|
259
|
|
|
|
|
|
|
);
|
260
|
|
|
|
|
|
|
|
261
|
49
|
100
|
|
|
|
224
|
return wantarray ? @row : \@row;
|
262
|
|
|
|
|
|
|
}
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head2 coordinates
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Returns the latitude and longitude coordinates of the station in
|
267
|
|
|
|
|
|
|
decimal format as a space-separated string.
|
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=cut
|
270
|
|
|
|
|
|
|
|
271
|
3669
|
|
|
3669
|
1
|
9717
|
method coordinates {
|
272
|
|
|
|
|
|
|
# uncoverable branch true
|
273
|
|
|
|
|
|
|
# uncoverable condition left
|
274
|
|
|
|
|
|
|
# uncoverable condition right
|
275
|
3669
|
50
|
33
|
|
|
12346
|
return $EMPTY unless $lat and $long;
|
276
|
3669
|
|
|
|
|
33983
|
return sprintf '%f %f', $lat, $long;
|
277
|
|
|
|
|
|
|
}
|
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head2 description
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
Return lines of text which describe the station in attribute: value
|
282
|
|
|
|
|
|
|
format.
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=cut
|
285
|
|
|
|
|
|
|
|
286
|
5
|
|
|
5
|
1
|
604
|
method description {
|
287
|
|
|
|
|
|
|
# uncoverable branch true
|
288
|
5
|
50
|
|
|
|
18
|
my $is_gsn = $gsn ? 'yes' : 'no';
|
289
|
5
|
|
|
|
|
37
|
my $elems = join q( ), sort keys $elems_href->%*;
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# note: those the values are lined up here, they won't be when
|
292
|
|
|
|
|
|
|
# imported into Google Earth
|
293
|
5
|
|
|
|
|
90
|
my $text = <<~"_EOT_";
|
294
|
|
|
|
|
|
|
Id: $id
|
295
|
|
|
|
|
|
|
Name: $name
|
296
|
|
|
|
|
|
|
Country: $country
|
297
|
|
|
|
|
|
|
State: $state
|
298
|
|
|
|
|
|
|
Active: $active
|
299
|
|
|
|
|
|
|
Coord: $lat $long
|
300
|
|
|
|
|
|
|
Elev: $elev
|
301
|
|
|
|
|
|
|
Is GSN? $is_gsn
|
302
|
|
|
|
|
|
|
Metrics: $elems
|
303
|
|
|
|
|
|
|
_EOT_
|
304
|
|
|
|
|
|
|
|
305
|
5
|
|
|
|
|
19
|
return $text;
|
306
|
|
|
|
|
|
|
}
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head2 error_count
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Returns a count of the number of errors that were flagged for this
|
311
|
|
|
|
|
|
|
station. Errors generally make the station unsuitable for use.
|
312
|
|
|
|
|
|
|
Warnings are not included.
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=cut
|
315
|
|
|
|
|
|
|
|
316
|
3676
|
|
|
3676
|
1
|
7887
|
method error_count {
|
317
|
3676
|
|
|
|
|
7367
|
my $err_count = grep { $_ < $ERR_THRESHOLD } $note_nrs->as_array;
|
|
6019
|
|
|
|
|
114228
|
|
318
|
|
|
|
|
|
|
|
319
|
3676
|
|
|
|
|
14567
|
return $err_count;
|
320
|
|
|
|
|
|
|
}
|
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head2 grid
|
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Returns the latitude and longitude to a single decimal place and using
|
325
|
|
|
|
|
|
|
cardinal (N/S E/W) notation. This value can be used for grouping
|
326
|
|
|
|
|
|
|
together stations that are within a 1/10th degree grid and which
|
327
|
|
|
|
|
|
|
may be assumed to experience similar weather conditions.
|
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=cut
|
330
|
|
|
|
|
|
|
|
331
|
790
|
|
|
790
|
1
|
1491
|
method grid {
|
332
|
790
|
|
|
|
|
1603
|
my ($x, $y) = ($lat, $long);
|
333
|
|
|
|
|
|
|
# uncoverable branch true
|
334
|
790
|
50
|
|
|
|
1761
|
my $xh = $x < 0 ? 'S' : 'N';
|
335
|
|
|
|
|
|
|
# uncoverable branch false
|
336
|
790
|
50
|
|
|
|
1541
|
my $yh = $y < 0 ? 'W' : 'E';
|
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
## no critic [ProhibitMagicNumbers]
|
339
|
|
|
|
|
|
|
# uncoverable branch true
|
340
|
790
|
50
|
|
|
|
1484
|
$x *= $x < 0 ? -1 : 1;
|
341
|
|
|
|
|
|
|
# uncoverable branch false
|
342
|
790
|
50
|
|
|
|
1284
|
$y *= $y < 0 ? -1 : 1;
|
343
|
|
|
|
|
|
|
|
344
|
790
|
|
|
|
|
4540
|
my $grid = sprintf '%4.1f%s %4.1f%s', $x, $xh, $y, $yh;
|
345
|
|
|
|
|
|
|
|
346
|
790
|
|
|
|
|
2275
|
return $grid;
|
347
|
|
|
|
|
|
|
}
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head2 selected
|
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
Returns a boolean indicating whether the station was selected for
|
352
|
|
|
|
|
|
|
data loading. Selected stations are those that meet the filtering
|
353
|
|
|
|
|
|
|
criteria (station id, station name, active range etc.) and that
|
354
|
|
|
|
|
|
|
are not flagged with errors.
|
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=cut
|
357
|
|
|
|
|
|
|
|
358
|
1
|
|
|
1
|
1
|
4
|
method selected {
|
359
|
|
|
|
|
|
|
# uncoverable branch true
|
360
|
1
|
50
|
|
|
|
5
|
return $note_nrs->cardinality == 0 ? $TRUE : $FALSE;
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=head2 url
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Returns the URL for the station's daily data web page in the NOAA
|
366
|
|
|
|
|
|
|
GHCN data repository.
|
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=cut
|
369
|
|
|
|
|
|
|
|
370
|
1
|
|
|
1
|
1
|
4
|
method url {
|
371
|
1
|
|
|
|
|
10
|
return $NOAA_DATA . $id . '.dly';
|
372
|
|
|
|
|
|
|
}
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head2 DOES
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Defined by Object::Pad. Included for POD::Coverage.
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head2 META
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Defined by Object::Pad. Included for POD::Coverage.
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head1 AUTHOR
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
Gary Puckering (jgpuckering@rogers.com)
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT
|
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
Copyright 2022, Gary Puckering
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=cut
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
1;
|