Skip to content

Commit c7fae87

Browse files
authored
Added TRIGGER=auto as a config option for vortex model hindcasts to eliminate a need to generate mock xml forecasts (#1263)
Issue 1247: * Added support for TRIGGER=auto to support one shot hindcasting for vortex models * Corrected exit condition Resolves #1247.
1 parent a2a9983 commit c7fae87

File tree

4 files changed

+81
-66
lines changed

4 files changed

+81
-66
lines changed

asgs_main.sh

+3-4
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ downloadCycloneData()
10231023
fi
10241024
fi
10251025
;;
1026-
"rss" | "rssembedded" )
1026+
"rss" | "rssembedded" | "auto" )
10271027
# if there was a new advisory, the $GET_ATCF_SCRIPT script (default is get_atcf.pl)
10281028
# would have returned the advisory number in stdout
10291029
if [[ ! -z $newAdvisoryNum && $newAdvisoryNum != null ]]; then
@@ -1034,7 +1034,7 @@ downloadCycloneData()
10341034
fi
10351035
;;
10361036
*)
1037-
fatal "$THIS: Invalid 'TRIGGER' type: '$TRIGGER'; must be ftp, rss, rssembedded, or atcf."
1037+
fatal "$THIS: Invalid 'TRIGGER' type: '$TRIGGER'; must be ftp, rss, rssembedded, auto, or atcf."
10381038
;;
10391039
esac
10401040
if [ $START = coldstart ]; then
@@ -3273,8 +3273,7 @@ while [ true ]; do
32733273
if [[ $RUNNOWCAST = yes ]]; then
32743274
OLDADVISDIR=$ADVISDIR
32753275
fi
3276-
if [[ $ONESHOT = yes || $NOFORCING = true ]]; then
3277-
wait # allow any background processes to complete
3276+
if [[ $ONESHOT = yes || $NOFORCING = true || $TRIGGER = auto ]]; then
32783277
exit $OK # exit because the ASGS will be started again later
32793278
fi
32803279
CYCLELOG=null

config/forcing_defaults.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# forcing_defaults.sh : Functions required for initializing
44
# parameters that are only related to the forcing.
55
#----------------------------------------------------------------
6-
# Copyright(C) 2019--2023 Jason Fleming
6+
# Copyright(C) 2019--2024 Jason Fleming
77
#
88
# This file is part of the ADCIRC Surge Guidance System (ASGS).
99
#
@@ -33,7 +33,7 @@ CYCLETIMELIMIT="05:00:00"
3333
#HDIR=${FDIR}
3434
STORM=07 # storm number, e.g. 05=ernesto in 2006
3535
YEAR=2018 # year of the storm
36-
TRIGGER="rssembedded" # either "ftp" or "rss"
36+
TRIGGER="rssembedded" # ftp|rss|rssembedded|ATCF|auto
3737
RSSSITE="www.nhc.noaa.gov" # site information for retrieving advisories
3838
FTPSITE="ftp.nhc.noaa.gov" # hindcast/nowcast ATCF formatted files
3939
FDIR="/atcf/afst" # forecast dir on nhc ftp site

get_atcf.pl

+61-53
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@
44
# This script downloads the latest raw hindcast and forecast from
55
# the NHC.
66
#
7-
# It can also load the hindcast and forecast files from the local
7+
# It can also load the hindcast and forecast files from the local
88
# file system.
99
#
1010
#--------------------------------------------------------------
11-
# Copyright(C) 2006--2018 Jason Fleming
11+
# Copyright(C) 2006--2024 Jason Fleming
1212
# Copyright(C) 2006, 2007 Brett Estrade
13-
#
13+
#
1414
# This file is part of the ADCIRC Surge Guidance System (ASGS).
15-
#
15+
#
1616
# The ASGS is free software: you can redistribute it and/or modify
1717
# it under the terms of the GNU General Public License as published by
1818
# the Free Software Foundation, either version 3 of the License, or
1919
# (at your option) any later version.
20-
#
20+
#
2121
# ASGS is distributed in the hope that it will be useful,
2222
# but WITHOUT ANY WARRANTY; without even the implied warranty of
2323
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2424
# GNU General Public License for more details.
25-
#
25+
#
2626
# You should have received a copy of the GNU General Public License
2727
# along with the ASGS. If not, see <http://www.gnu.org/licenses/>.
2828
#
@@ -35,27 +35,29 @@
3535
use Net::SSLeay;
3636
use Getopt::Long;
3737
#
38-
my $statefile="null"; # shell script with variables and values that
38+
my $statefile="null"; # shell script with variables and values that
3939
# record the current state of the ASGS
4040
our %state; # represents current state of ASGS
41-
my $ftpsite; # hostname for hindcast, nowcast, and/or forecast data
41+
my $ftpsite; # hostname for hindcast, nowcast, and/or forecast data
4242
# $ftpsite can also be set to "filesystem" to pick up these
4343
# data from the local filesystem
4444
my $rsssite; # hostname where the RSS feed (index-at.xml) is located
4545
# $rsssite can also be set to "filesystem" to pick up these
4646
# data from the local filesystem
4747
my $fdir; # directory on $ftpsite for ATCF formatted forecast data
4848
my $hdir; # directory on $ftpsite for ATCF formatted hindcast data
49-
my $storm; # two digit NHC storm number
50-
my $year; # four digit year of the storm
49+
my $storm; # two digit NHC storm number
50+
my $year; # four digit year of the storm
5151
my $adv; # formatted advisory number of the previous advisory, if any
5252
my $trigger = "rss"; # the data source used to detect a new advisory
53-
# can also be set to "rssembedded" to get the advisory text
53+
# can also be set to "rssembedded" to get the advisory text
5454
# that is embedded in the RSS xml file, rather than following
5555
# the external link to the text of the forecast/advisory
5656
my $nhcName; # the name given by the NHC, e.g., TWO, GUSTAV, KATRINA, etc
5757
my $insecure;# if set, use "http" instead of "https"
5858
my $body; # text of the forecast/advisory
59+
my $advNum; # advisory number detected from the BEST/OFCL data feeds
60+
my $newAdvisory = 0;
5961
GetOptions(
6062
"statefile=s" => \$statefile,
6163
"rsssite=s" => \$rsssite,
@@ -80,13 +82,13 @@
8082
my $fcDl = 0; # true if the forecast was downloaded successfully
8183

8284
while (!$dl) {
83-
$hcDl = 0;
85+
$hcDl = 0;
8486
$fcDl = 0;
8587
my $ftp;
8688
#
8789
# OPEN FTP SESSION (if needed)
8890
if ( $ftpsite ne "filesystem" ) {
89-
$ftp = Net::FTP->new($ftpsite, Debug => 1, Passive => 1);
91+
$ftp = Net::FTP->new($ftpsite, Debug => 1, Passive => 1);
9092
unless ( defined $ftp ) {
9193
stderrMessage("ERROR","ftp: Cannot connect to $ftpsite: $@");
9294
next;
@@ -102,11 +104,11 @@
102104
if ( $ftpsite eq "filesystem" ) {
103105
# we are getting the hindcast from the local filesystem
104106
if ( -e $hdir && -d $hdir ) {
105-
$hcDl = 1;
107+
$hcDl = 1;
106108
} else {
107-
stderrMessage("ERROR","Get '$hindcastfile' failed: "
109+
stderrMessage("ERROR","Get '$hindcastfile' failed: "
108110
. " the local directory $hdir does not exist, or is not a directory.");
109-
next;
111+
next;
110112
}
111113
} else {
112114
# we are getting the hindcast from an ftp server
@@ -127,18 +129,18 @@
127129
# grab the name of the storm from the hindcast, if it was not provided
128130
# in the command line parameters
129131
unless ( $nhcName ) {
130-
if ( $hcDl ) {
132+
if ( $hcDl ) {
131133
my $hcOpenSuccess;
132134
if ( $ftpsite eq "filesystem" ) {
133135
$hcOpenSuccess = open(HINDCAST,"<$hdir/$hindcastfile");
134136
} else {
135-
$hcOpenSuccess = open(HINDCAST,"<$hindcastfile");
137+
$hcOpenSuccess = open(HINDCAST,"<$hindcastfile");
136138
}
137-
unless ($hcOpenSuccess) {
138-
stderrMessage("ERROR","Could not open hindcast file '$hindcastfile'.");
139+
unless ($hcOpenSuccess) {
140+
stderrMessage("ERROR","Could not open hindcast file '$hindcastfile'.");
139141
next;
140142
}
141-
# grab the last defined name in the hindcast
143+
# grab the last defined name in the hindcast
142144
while(<HINDCAST>) {
143145
my @line = split(",",$_);
144146
foreach my $j (@line) {
@@ -149,7 +151,7 @@
149151
}
150152
}
151153
close(HINDCAST);
152-
} else {
154+
} else {
153155
stderrMessage("ERROR","Could not get NHC Name from hindcast " .
154156
"because the download of the hindcast file '$hindcastfile' " .
155157
"was not successful; " .
@@ -158,23 +160,31 @@
158160
next;
159161
}
160162
}
161-
#
163+
#
162164
# FORECAST TRACK
165+
if ( $trigger eq "auto" ) {
166+
# there is no forecast track; the forecast track file will not be written
167+
$advNum = "00";
168+
$fcDl = 1;
169+
$newAdvisory = 1;
170+
stderrMessage("DEBUG","The new advisory number is $advNum.");
171+
printf STDOUT "$advNum";
172+
}
163173
if ( $trigger eq "ftp" ) {
164174
my $fcDirSuccess = $ftp->cwd($fdir);
165-
unless ( $fcDirSuccess ) {
175+
unless ( $fcDirSuccess ) {
166176
stderrMessage("ERROR",
167-
"ftp: Cannot change working directory to '$fdir': "
177+
"ftp: Cannot change working directory to '$fdir': "
168178
. $ftp->message);
169179
next;
170180
}
171181
$fcDl = $ftp->get($forecastfile);
172182
unless ($fcDl) {
173-
stderrMessage("ERROR","ftp: Get '$forecastfile' failed: "
183+
stderrMessage("ERROR","ftp: Get '$forecastfile' failed: "
174184
. $ftp->message);
175185
next;
176186
}
177-
# save the advisory number by parsing the name of the file that the
187+
# save the advisory number by parsing the name of the file that the
178188
# file points to (a hack for our ftp test rig)
179189
if ( $ftpsite =~ /ftp.unc.edu/ ) {
180190
my @advisoryDir = $ftp->dir($fdir);
@@ -199,12 +209,12 @@
199209
if ( $trigger eq "rss" || $trigger eq "rssembedded" ) {
200210
# pick up the RSS feed from the local filesystem
201211
if ( $rsssite eq "filesystem" ) {
202-
if ( -e "$fdir/index-at.xml" ) {
212+
if ( -e "$fdir/index-at.xml" ) {
203213
unless (open(FORECAST,"<$fdir/index-at.xml")) {
204214
stderrMessage("ERROR","Cannot open the file $fdir/index-at.xml: $!");
205215
next;
206216
}
207-
# stuff the lines of the forecast into a string variable;
217+
# stuff the lines of the forecast into a string variable;
208218
# this mimics what happens if we download the RSS feed from
209219
# the web
210220
$body = '';
@@ -214,7 +224,7 @@
214224
close(FORECAST);
215225
} else {
216226
stderrMessage("ERROR","Cannot find the file $fdir/index-at.xml.");
217-
next;
227+
next;
218228
}
219229
} else {
220230
# pick up the RSS feed from the web
@@ -237,7 +247,7 @@
237247
my $url = sprintf("%s://%s/index-at.xml", $protocol, $rsssite);
238248
my $response = $http->get($url);
239249

240-
if ( $response->{status} == 599 ) {
250+
if ( $response->{status} == 599 ) {
241251
stderrMessage("ERROR","Failed to download forecast/advisory.");
242252
printf STDERR "content: ";
243253
print STDERR $response->{content};
@@ -262,27 +272,25 @@
262272
my $i=0;
263273
my $textAdvisoryHost;
264274
my $textAdvisoryPath;
265-
my $advNum;
266275
my $stormFound = 0;
267276
my $linkFound = 0;
268-
my $newAdvisory = 0;
269-
# printf STDERR "INFO: get_atcf.pl:
277+
# printf STDERR "INFO: get_atcf.pl:
270278
# The index-at.xml file contains $cnt lines.\n";
271279
# Loop over the body of the index file, looking for our storm.
272280
#
273281
# jgf20140804: The storm name may have changed in the forecast, causing
274282
# the storm name in the best track file to be outdated and different
275283
# from the storm name found here. For example, in 2014, TD ONE changed
276284
# to TS ARTHUR, and TD TWO changed to TS BERTHA. Therefore, we must
277-
# look for the advisory by storm number, not name.
285+
# look for the advisory by storm number, not name.
278286
while ($i<$cnt) {
279287
# TROPICAL STORM BERTHA FORECAST/ADVISORY NUMBER 22
280288
# NWS NATIONAL HURRICANE CENTER MIAMI FL AL032014
281289
# pre-2006:
282290
# NWS TPC/NATIONAL HURRICANE CENTER MIAMI FL AL182005
283291
if ( $lines[$i] =~ /NATIONAL HURRICANE CENTER MIAMI FL\s+AL(\d{2})(\d{4})/ ) {
284292
if ($1 == $storm && $2 == $year && $lines[$i-1] =~ /FORECAST.ADVISORY/ ) {
285-
# we have found the entry containing info about the
293+
# we have found the entry containing info about the
286294
# latest advisory for our storm
287295
$stormFound = 1;
288296
# get the advisory number from the previous line
@@ -300,7 +308,7 @@
300308
}
301309
}
302310
#
303-
# reset the line number to the beginning of the NHC
311+
# reset the line number to the beginning of the NHC
304312
# forecast/advisory text, and grab the whole of the advisory,
305313
# storing it in the $body variable
306314
$i -= 8;
@@ -318,7 +326,7 @@
318326
last;
319327
}
320328
} else {
321-
# just grab the link to the actual text of the advisory
329+
# just grab the link to the actual text of the advisory
322330
# from a webserver
323331
if ( $lines[$i] =~ /<link>http:\/\/(.*?)\/(.*)<\/link>/ ) {
324332
$linkFound = 1;
@@ -340,24 +348,24 @@
340348
}
341349
}
342350
}
343-
}
344-
last;
351+
}
352+
last;
345353
}
346-
}
354+
}
347355
$i++;
348356
}
349-
unless ( $stormFound ) {
357+
unless ( $stormFound ) {
350358
stderrMessage("ERROR","http: The storm number $storm (named '$nhcName') of $year was not found in the RSS feed.");
351359
#stderrMessage("DEBUG","The body of the index-at.xml file was $body.");
352360
next;
353361
}
354362
# if we are supposed to get the text of the forecast file from
355363
# link in the RSS feed, and we find no such link, we are toast
356-
if ( $trigger eq "rss" && !$linkFound ) {
364+
if ( $trigger eq "rss" && !$linkFound ) {
357365
stderrMessage("ERROR","http: The link to the Forecast/Advisory for the storm named '$nhcName' was not found in the index file of the RSS feed.");
358366
next;
359367
}
360-
unless ( $newAdvisory ) {
368+
unless ( $newAdvisory ) {
361369
#nld wait a bit here to slow down repeated checks to http site stderrMessage("INFO","Napping.");
362370
sleep 60;
363371
next;
@@ -372,7 +380,7 @@
372380
next;
373381
}
374382
my $advReqSuccess = $advConnect->write_request(
375-
GET => "/$textAdvisoryPath",
383+
GET => "/$textAdvisoryPath",
376384
'User-Agent' => "Mozilla/5.0");
377385
unless ($advReqSuccess) {
378386
stderrMessage("ERROR",
@@ -381,7 +389,7 @@
381389
}
382390
my ($code, $mess, %h) = $advConnect->read_response_headers();
383391
$body="";
384-
while(1) {
392+
while(1) {
385393
my $buf;
386394
my $n = $advConnect->read_entity_body($buf,1024);
387395
unless ( defined $n ) {
@@ -396,12 +404,12 @@
396404
# the local file system, and we have successfully parsed out the
397405
# full path and file name of the file that contains the text of the
398406
# advsiory, then load it up in $body to mimic what would have happened
399-
# if we had downloaded it via http
407+
# if we had downloaded it via http
400408
if ( $rsssite eq "filesystem" and defined $textAdvisoryPath and not defined $textAdvisoryHost ) {
401409
unless ( -e $textAdvisoryPath ) {
402410
stderrMessage("ERROR","The file containing the full text of the forecast advisory ('$textAdvisoryPath', pulled from the link in the RSS feed) does not exist.");
403-
next;
404-
}
411+
next;
412+
}
405413
unless ( open(ADVTEXT,"<$textAdvisoryPath") ) {
406414
stderrMessage("ERROR","Could not open '$textAdvisoryPath' to read: $!");
407415
next;
@@ -412,8 +420,8 @@
412420
close(ADVTEXT);
413421
}
414422
# now write out the file, which may contain html or other extraneous
415-
# data, so that the relevant data can be parsed out
416-
# by nhc_advisory_bot.pl
423+
# data, so that the relevant data can be parsed out
424+
# by nhc_advisory_bot.pl
417425
my $textAdvFile = $forecastfile . ".html";
418426
my $openTxtForecastSuccess = open(TEXTFORECAST,">$textAdvFile");
419427
unless ($openTxtForecastSuccess) {
@@ -425,7 +433,7 @@
425433
$fcDl=1;
426434
}
427435

428-
if ( $hcDl && $fcDl ) {
436+
if ( $hcDl && $fcDl ) {
429437
$dl=1;
430438
} else {
431439
sleep 60;
@@ -458,7 +466,7 @@ ()
458466
#$k =~ s/\s+//g;
459467
# remove leading and trailing whitespaces from the key
460468
$k =~ s/^\s+//g;
461-
$k =~ s/\s+$//g;
469+
$k =~ s/\s+$//g;
462470
# remove whitespace from the value
463471
$v =~ s/\s+//g;
464472
$H{$k}=$v;

0 commit comments

Comments
 (0)